2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
6
* The contents of this file are subject to the terms of either the GNU
7
* General Public License Version 2 only ("GPL") or the Common
8
* Development and Distribution License("CDDL") (collectively, the
9
* "License"). You may not use this file except in compliance with the
10
* License. You can obtain a copy of the License at
11
* http://www.netbeans.org/cddl-gplv2.html
12
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
* specific language governing permissions and limitations under the
14
* License. When distributing the software, include this License Header
15
* Notice in each file and include the License file at
16
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17
* particular file as subject to the "Classpath" exception as provided
18
* by Sun in the GPL Version 2 section of the License file that
19
* accompanied this code. If applicable, add the following below the
20
* License Header, with the fields enclosed by brackets [] replaced by
21
* your own identifying information:
22
* "Portions Copyrighted [year] [name of copyright owner]"
26
* The Original Software is NetBeans. The Initial Developer of the Original
27
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
* Microsystems, Inc. All Rights Reserved.
30
* If you wish your version of this file to be governed by only the CDDL
31
* or only the GPL Version 2, indicate your decision by adding
32
* "[Contributor] elects to include this software in this distribution
33
* under the [CDDL or GPL Version 2] license." If you do not indicate a
34
* single choice of license, a recipient has the option to distribute
35
* your version of this file under either the CDDL, the GPL Version 2 or
36
* to extend the choice of license to its licensees as provided above.
37
* However, if you add GPL Version 2 code and therefore, elected the GPL
38
* Version 2 license, then the option applies only if the new code is
39
* made subject to such option by the copyright holder.
42
package org.netbeans.core.windows.persistence;
44
import java.util.logging.Level;
45
import org.netbeans.core.windows.Debug;
46
import org.openide.filesystems.FileLock;
47
import org.openide.filesystems.FileObject;
48
import org.openide.filesystems.FileUtil;
49
import org.openide.modules.SpecificationVersion;
50
import org.openide.util.NbBundle;
52
import org.xml.sax.helpers.DefaultHandler;
55
import java.util.logging.Logger;
58
* Handle loading/saving of TopComponent reference in Group configuration data.
65
public static final String INSTANCE_DTD_ID_2_0
66
= "-//NetBeans//DTD Top Component in Group Properties 2.0//EN"; // NOI18N
68
private static final boolean DEBUG = Debug.isLoggable(TCGroupParser.class);
70
/** Unique id from file name */
73
/** Module parent folder */
74
private FileObject moduleParentFolder;
76
/** Local parent folder */
77
private FileObject localParentFolder;
79
private InternalConfig internalConfig;
81
/** true if wstcgrp file is present in module folder */
82
private boolean inModuleFolder;
83
/** true if wstcgrp file is present in local folder */
84
private boolean inLocalFolder;
86
public TCGroupParser(String tc_id) {
90
/** Load tcgroup configuration. */
91
TCGroupConfig load () throws IOException {
92
if (DEBUG) Debug.log(TCGroupParser.class, "load ENTER" + " tcGrp:" + tc_id);
93
TCGroupConfig tcGroupCfg = new TCGroupConfig();
94
PropertyHandler propertyHandler = new PropertyHandler();
95
InternalConfig internalCfg = getInternalConfig();
97
propertyHandler.readData(tcGroupCfg, internalCfg);
98
if (DEBUG) Debug.log(TCGroupParser.class, "load LEAVE" + " tcGrp:" + tc_id);
102
/** Save tcGroup configuration. */
103
void save (TCGroupConfig tcGroupCfg) throws IOException {
104
if (DEBUG) Debug.log(TCGroupParser.class, "save ENTER" + " tcGrp:" + tc_id);
106
PropertyHandler propertyHandler = new PropertyHandler();
107
InternalConfig internalCfg = getInternalConfig();
108
propertyHandler.writeData(tcGroupCfg, internalCfg);
109
if (DEBUG) Debug.log(TCGroupParser.class, "save LEAVE" + " tcGrp:" + tc_id);
116
/** Getter for internal configuration data.
117
* @return instance of internal configuration data
119
InternalConfig getInternalConfig () {
120
if (internalConfig == null) {
121
internalConfig = new InternalConfig();
123
return internalConfig;
126
boolean isInModuleFolder () {
127
return inModuleFolder;
130
void setInModuleFolder (boolean inModuleFolder) {
131
this.inModuleFolder = inModuleFolder;
134
boolean isInLocalFolder () {
135
return inLocalFolder;
138
void setInLocalFolder (boolean inLocalFolder) {
139
this.inLocalFolder = inLocalFolder;
142
void setModuleParentFolder (FileObject moduleParentFolder) {
143
this.moduleParentFolder = moduleParentFolder;
146
void setLocalParentFolder (FileObject localParentFolder) {
147
this.localParentFolder = localParentFolder;
150
void log (String s) {
151
Debug.log(TCGroupParser.class, s);
154
private final class PropertyHandler extends DefaultHandler {
156
/** tcRef manager configuration data */
157
private TCGroupConfig tcGroupConfig = null;
159
/** internal configuration data */
160
private InternalConfig internalConfig = null;
162
/** Lock to prevent mixing readData and writeData */
163
private final Object RW_LOCK = new Object();
165
public PropertyHandler () {
168
private FileObject getConfigFOInput () {
169
FileObject tcGroupConfigFO;
170
if (isInLocalFolder()) {
171
//log("-- TCGroupParser.getConfigFOInput" + " looking for LOCAL");
172
tcGroupConfigFO = localParentFolder.getFileObject
173
(TCGroupParser.this.getName(), PersistenceManager.TCGROUP_EXT);
174
} else if (isInModuleFolder()) {
175
//log("-- TCGroupParser.getConfigFOInput" + " looking for MODULE");
176
tcGroupConfigFO = moduleParentFolder.getFileObject
177
(TCGroupParser.this.getName(), PersistenceManager.TCGROUP_EXT);
179
//XXX should not happen
180
tcGroupConfigFO = null;
182
//log("-- TCGroupParser.getConfigFOInput" + " tcGroupConfigFO:" + tcGroupConfigFO);
183
return tcGroupConfigFO;
186
private FileObject getConfigFOOutput () throws IOException {
187
FileObject tcGroupConfigFO;
188
tcGroupConfigFO = localParentFolder.getFileObject
189
(TCGroupParser.this.getName(), PersistenceManager.TCGROUP_EXT);
190
if (tcGroupConfigFO != null) {
191
//log("-- TCGroupParser.getConfigFOOutput" + " tcGroupConfigFO LOCAL:" + tcGroupConfigFO);
192
return tcGroupConfigFO;
194
StringBuffer buffer = new StringBuffer();
195
buffer.append(TCGroupParser.this.getName());
197
buffer.append(PersistenceManager.TCGROUP_EXT);
198
//XXX should be improved localParentFolder can be null
199
tcGroupConfigFO = FileUtil.createData(localParentFolder, buffer.toString());
200
//log("-- TCGroupParser.getConfigFOOutput" + " LOCAL not found CREATE");
202
return tcGroupConfigFO;
206
Reads tcRef configuration data from XML file.
207
Data are returned in output params.
209
void readData (TCGroupConfig tcGroupCfg, InternalConfig internalCfg)
211
tcGroupConfig = tcGroupCfg;
212
internalConfig = internalCfg;
214
FileObject cfgFOInput = getConfigFOInput();
215
if (cfgFOInput == null) {
216
throw new FileNotFoundException("[WinSys] Missing TCGroup configuration file:" // NOI18N
217
+ TCGroupParser.this.getName());
219
InputStream is = null;
221
synchronized (RW_LOCK) {
223
/*InputStream is = cfgFOInput.getInputStream();
224
byte [] arr = new byte [is.available()];
226
log("DUMP TCGroup: " + TCGroupParser.this.getName());
227
String s = new String(arr);
230
is = cfgFOInput.getInputStream();
231
PersistenceManager.getDefault().getXMLParser(this).parse(new InputSource(is));
233
} catch (SAXException exc) {
234
// Turn into annotated IOException
235
String msg = NbBundle.getMessage(TCGroupParser.class,
236
"EXC_TCGroupParse", cfgFOInput);
238
throw (IOException) new IOException(msg).initCause(exc);
244
} catch (IOException exc) {
245
Logger.getLogger(TCGroupParser.class.getName()).log(Level.WARNING, null, exc);
249
tcGroupCfg = tcGroupConfig;
250
internalCfg = internalConfig;
252
tcGroupConfig = null;
253
internalConfig = null;
256
public void startElement (String nameSpace, String name, String qname, Attributes attrs)
257
throws SAXException {
258
if ("tc-group".equals(qname)) { // NOI18N
259
handleTCGroup(attrs);
260
} else if (internalConfig.specVersion.compareTo(new SpecificationVersion("2.0")) == 0) { // NOI18N
262
if ("module".equals(qname)) { // NOI18N
264
} else if ("tc-id".equals(qname)) { // NOI18N
266
} else if ("open-close-behavior".equals(qname)) { // NOI18N
267
handleOpenCloseBehavior(attrs);
270
log("-- TCGroupParser.startElement PARSING OLD");
271
//Parse version < 2.0
275
public void error(SAXParseException ex) throws SAXException {
279
/** Reads element "tc-group" */
280
private void handleTCGroup (Attributes attrs) {
281
String version = attrs.getValue("version"); // NOI18N
282
if (version != null) {
283
internalConfig.specVersion = new SpecificationVersion(version);
285
PersistenceManager.LOG.log(Level.WARNING,
286
"[WinSys.TCGroupParser.handleTCGroup]" // NOI18N
287
+ " Warning: Missing attribute \"version\" of element \"tc-group\"."); // NOI18N
288
internalConfig.specVersion = new SpecificationVersion("2.0"); // NOI18N
292
/** Reads element "module" and updates mode config content */
293
private void handleModule (Attributes attrs) {
294
String moduleCodeName = attrs.getValue("name"); // NOI18N
296
internalConfig.moduleCodeNameBase = null;
297
internalConfig.moduleCodeNameRelease = null;
298
internalConfig.moduleSpecificationVersion = null;
299
if (moduleCodeName != null) {
300
int i = moduleCodeName.indexOf('/');
302
internalConfig.moduleCodeNameBase = moduleCodeName.substring(0, i);
303
internalConfig.moduleCodeNameRelease = moduleCodeName.substring(i + 1);
304
checkReleaseCode(internalConfig);
306
internalConfig.moduleCodeNameBase = moduleCodeName;
308
internalConfig.moduleSpecificationVersion = attrs.getValue("spec"); // NOI18N
312
/** Checks validity of <code>moduleCodeNameRelease</code> field.
314
private void checkReleaseCode (InternalConfig internalConfig) {
315
// #24844. Repair the wrongly saved "null" string
316
// as release number.
317
if("null".equals(internalConfig.moduleCodeNameRelease)) { // NOI18N
318
Logger.getLogger(TCGroupParser.class.getName()).log(Level.WARNING, null,
319
new IllegalStateException("Module release code was saved as null string" +
321
internalConfig.moduleCodeNameBase +
323
internalConfig.moduleCodeNameRelease = null;
327
/** Reads element "tc-id" */
328
private void handleTcId (Attributes attrs) throws SAXException {
329
String tc_id = attrs.getValue("id"); // NOI18N
331
tcGroupConfig.tc_id = tc_id;
332
if (!tc_id.equals(TCGroupParser.this.getName())) {
333
PersistenceManager.LOG.log(Level.WARNING,
334
"[WinSys.TCGroupParser.handleTcId]" // NOI18N
335
+ " Error: Value of attribute \"id\" of element \"tc-id\"" // NOI18N
336
+ " and configuration file name must be the same."); // NOI18N
337
throw new SAXException("Invalid attribute value"); // NOI18N
340
PersistenceManager.LOG.log(Level.WARNING,
341
"[WinSys.TCGroupParser.handleTcId]" // NOI18N
342
+ " Error: Missing required attribute \"id\" of element \"tc-id\"."); // NOI18N
343
throw new SAXException("Missing required attribute"); // NOI18N
347
/** Reads element "open-close-behavior" */
348
private void handleOpenCloseBehavior (Attributes attrs) throws SAXException {
349
String open = attrs.getValue("open"); // NOI18N;
351
if ("true".equals(open)) { // NOI18N
352
tcGroupConfig.open = true;
353
} else if ("false".equals(open)) { // NOI18N
354
tcGroupConfig.open = false;
356
PersistenceManager.LOG.log(Level.WARNING,
357
"[WinSys.TCGroupParser.handleOpenCloseBehavior]" // NOI18N
358
+ " Warning: Invalid value of attribute \"open\"" // NOI18N
359
+ " of element \"open-close-behavior\"."); // NOI18N
360
tcGroupConfig.open = false;
363
PersistenceManager.LOG.log(Level.WARNING,
364
"[WinSys.TCGroupParser.handleOpenCloseBehavior]" // NOI18N
365
+ " Warning: Missing required attribute \"open\"" // NOI18N
366
+ " of element \"open-close-behavior\"."); // NOI18N
367
tcGroupConfig.open = false;
370
String close = attrs.getValue("close"); // NOI18N;
372
if ("true".equals(close)) { // NOI18N
373
tcGroupConfig.close = true;
374
} else if ("false".equals(close)) { // NOI18N
375
tcGroupConfig.close = false;
377
PersistenceManager.LOG.log(Level.WARNING,
378
"[WinSys.TCGroupParser.handleOpenCloseBehavior]" // NOI18N
379
+ " Warning: Invalid value of attribute \"close\"" // NOI18N
380
+ " of element \"open-close-behavior\"."); // NOI18N
381
tcGroupConfig.close = false;
384
PersistenceManager.LOG.log(Level.WARNING,
385
"[WinSys.TCGroupParser.handleOpenCloseBehavior]" // NOI18N
386
+ " Warning: Missing required attribute \"close\"" // NOI18N
387
+ " of element \"open-close-behavior\"."); // NOI18N
388
tcGroupConfig.close = false;
391
String wasOpened = attrs.getValue("was-opened"); // NOI18N;
392
if (wasOpened != null) {
393
if ("true".equals(wasOpened)) { // NOI18N
394
tcGroupConfig.wasOpened = true;
395
} else if ("false".equals(wasOpened)) { // NOI18N
396
tcGroupConfig.wasOpened = false;
398
PersistenceManager.LOG.log(Level.WARNING,
399
"[WinSys.TCGroupParser.handleOpenCloseBehavior]" // NOI18N
400
+ " Warning: Invalid value of attribute \"was-opened\"" // NOI18N
401
+ " of element \"open-close-behavior\"."); // NOI18N
402
tcGroupConfig.wasOpened = false;
405
tcGroupConfig.wasOpened = false;
409
/** Writes data from asociated tcRef to the xml representation */
410
void writeData (TCGroupConfig tcGroupCfg, InternalConfig ic) throws IOException {
411
final StringBuffer buff = fillBuffer(tcGroupCfg, ic);
412
synchronized (RW_LOCK) {
413
FileObject cfgFOOutput = getConfigFOOutput();
414
FileLock lock = null;
415
OutputStream os = null;
416
OutputStreamWriter osw = null;
418
lock = cfgFOOutput.lock();
419
os = cfgFOOutput.getOutputStream(lock);
420
osw = new OutputStreamWriter(os, "UTF-8"); // NOI18N
421
osw.write(buff.toString());
422
//log("DUMP TCGroup: " + TCGroupParser.this.getName());
423
//log(buff.toString());
429
} catch (IOException exc) {
430
Logger.getLogger(TCGroupParser.class.getName()).log(Level.WARNING, null, exc);
439
/** Returns xml content in StringBuffer
441
private StringBuffer fillBuffer (TCGroupConfig tcGroupCfg, InternalConfig ic) throws IOException {
442
StringBuffer buff = new StringBuffer(800);
443
String curValue = null;
445
buff.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n"). // NOI18N
446
/*buff.append("<!DOCTYPE tc-group PUBLIC\n"); // NOI18N
447
buff.append(" \"-//NetBeans//DTD Top Component in Group Properties 2.0//EN\"\n"); // NOI18N
448
buff.append(" \"http://www.netbeans.org/dtds/tc-group2_0.dtd\">\n\n"); // NOI18N*/
449
append("<tc-group version=\"2.0\">\n"); // NOI18N
451
appendModule(ic, buff);
452
appendTcId(tcGroupCfg, buff);
453
appendOpenCloseBehavior(tcGroupCfg, buff);
455
buff.append("</tc-group>\n"); // NOI18N
459
private void appendModule (InternalConfig ic, StringBuffer buff) {
463
if (ic.moduleCodeNameBase != null) {
464
buff.append(" <module name=\""); // NOI18N
465
buff.append(ic.moduleCodeNameBase);
466
if (ic.moduleCodeNameRelease != null) {
467
buff.append("/").append(ic.moduleCodeNameRelease); // NOI18N
469
if (ic.moduleSpecificationVersion != null) {
470
buff.append("\" spec=\""); // NOI18N
471
buff.append(ic.moduleSpecificationVersion);
473
buff.append("\" />\n"); // NOI18N
477
private void appendTcId (TCGroupConfig tcGroupCfg, StringBuffer buff) {
478
buff.append(" <tc-id id=\"").append(
479
PersistenceManager.escapeTcId4XmlContent(tcGroupCfg.tc_id)).
480
append("\"/>\n"); // NOI18N
483
private void appendOpenCloseBehavior (TCGroupConfig tcGroupCfg, StringBuffer buff) {
484
buff.append(" <open-close-behavior open=\"").append(tcGroupCfg.open). // NOI18N
485
append("\" close=\"").append(tcGroupCfg.close). // NOI18N
486
append("\" was-opened=\"").append(tcGroupCfg.wasOpened).append("\"/>\n"); // NOI18N