Revision 42749

View differences:

tags/org.gvsig.desktop-2.0.131/org.gvsig.desktop.compat.cdc/org.gvsig.i18n/utils/test/src/org/gvsig/i18n/utils/TestProperties.java
1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.i18n.utils;
25

  
26
import java.io.File;
27
import java.io.FileInputStream;
28
import java.io.FileNotFoundException;
29
import java.io.FileOutputStream;
30
import java.io.IOException;
31
import java.io.InputStream;
32
import java.io.OutputStream;
33

  
34
import junit.framework.TestCase;
35

  
36
/**
37
 * @author cesar
38
 *
39
 */
40
public class TestProperties extends TestCase {
41
	static final String fileName = "TestProperties-file";
42
	InputStream is;
43
	OutputStream os;
44
	
45
	public void initOutputStream() {
46
		try {
47
			os = new FileOutputStream(fileName);
48
		} catch (FileNotFoundException e) {
49
			TestCase.fail(e.getLocalizedMessage());
50
		}
51
	}
52
	
53
	public void discardOutputStream() {
54
		try {
55
			os.close();
56
			File file = new File(fileName);
57
			file.delete();
58
		} catch (IOException e) {
59
			TestCase.fail(e.getLocalizedMessage());
60
		}
61
	}
62
	
63
	public void initInputStream() {
64
		try {
65
			is = new FileInputStream(fileName);
66
		} catch (FileNotFoundException e) {
67
			TestCase.fail(e.getLocalizedMessage());
68
		}
69
	}
70
	
71
	public void discardInputStream() {
72
		try {
73
			is.close();
74
		} catch (IOException e) {
75
			TestCase.fail(e.getLocalizedMessage());
76
		}
77
	}
78
	
79
	public void testOrderedPropertiesBasic() {
80
		// write file
81
		OrderedProperties props1 = new OrderedProperties();
82
		props1.setProperty("prueba", "hola");
83
		props1.setProperty("prueba2", "holas");
84
		props1.setProperty("abrir", "cerrar");
85
		props1.setProperty("puerta", "hembrilla");
86
		props1.setProperty("12libros", "quijote");
87
		props1.setProperty("ca?uto", "\u20acuropeo");
88
		props1.setProperty("confli=cto", "amigo");
89
		props1.setProperty("  confli =  :cto mayor ", " peque?o conflicto");
90
		initOutputStream();
91
		try {
92
			props1.store(os, "header");
93
		} catch (IOException e) {
94
			TestCase.fail(e.getLocalizedMessage());
95
		}
96
		
97
		// read file
98
		OrderedProperties props2 = new OrderedProperties();
99
		initInputStream();
100
		try {
101
			props2.load(is);
102
		} catch (IOException e) {
103
			TestCase.fail(e.getLocalizedMessage());
104
		}
105
		TestCase.assertEquals("\u20acuropeo", props2.getProperty("ca?uto"));
106
		TestCase.assertEquals("amigo", props2.getProperty("confli=cto"));
107
		TestCase.assertEquals(" peque?o conflicto", props2.getProperty("  confli =  :cto mayor "));
108
		TestCase.assertEquals("hola", props2.getProperty("prueba"));
109
		TestCase.assertEquals("holas", props2.getProperty("prueba2"));
110
		TestCase.assertEquals("cerrar", props2.getProperty("abrir"));
111
		TestCase.assertEquals("hembrilla", props2.getProperty("puerta"));
112
		TestCase.assertEquals("quijote", props2.getProperty("12libros"));
113
		discardInputStream();
114
		discardOutputStream();
115
	}
116

  
117
	
118
	public void testOrderedProperties() {
119
		// write file
120
		OrderedProperties props1 = new OrderedProperties();
121
		props1.setProperty("prueba", "hola");
122
		props1.setProperty("prueba2", "holas");
123
		props1.setProperty("ca?uto", "\u20acuropeo");
124
		props1.setProperty("confli=cto", "amigo");
125
		props1.setProperty("  conflis =  :cto mayor ", " peque?o conflicto");
126
		props1.setProperty("abrir", "cerrar");
127
		props1.setProperty("puerta", "hembrilla");
128
		props1.setProperty("12libros", "quijote");
129
		initOutputStream();
130
		try {
131
			props1.store(os, "header", "8859_15");
132
		} catch (IOException e) {
133
			TestCase.fail(e.getLocalizedMessage());
134
		}
135
		
136
		// read file
137
		OrderedProperties props2 = new OrderedProperties();
138
		initInputStream();
139
		try {
140
			props2.load(is, "8859_15");
141
		} catch (IOException e) {
142
			TestCase.fail(e.getLocalizedMessage());
143
		}
144
		// estos deber?an salir igual
145
		TestCase.assertEquals("hola", props2.getProperty("prueba"));
146
		TestCase.assertEquals("holas", props2.getProperty("prueba2"));
147
		TestCase.assertEquals("cerrar", props2.getProperty("abrir"));
148
		TestCase.assertEquals("hembrilla", props2.getProperty("puerta"));
149
		TestCase.assertEquals("quijote", props2.getProperty("12libros"));
150
		// con estos en cambio no obtenemos los mismos valores que escribimos anteriormente. Es normal, porque incluimos
151
		// caracteres especiales como ":" y "=". Para manejarlos correctamente necesitamos usas los m?todos load/store
152
		// sin encoding, los cuales s? escapan los caracteres especiales
153
		TestCase.assertEquals("\u20acuropeo", props2.getProperty("ca?uto"));
154
		TestCase.assertEquals("cto=amigo", props2.getProperty("confli"));
155
		TestCase.assertEquals(":cto mayor = peque?o conflicto", props2.getProperty("conflis"));
156

  
157
		discardInputStream();
158
		discardOutputStream();
159
		
160
		// write file
161
		props1 = new OrderedProperties();
162
		props1.setProperty("Prueba", "hola");
163
		props1.setProperty("prueba2", "holas");
164
		props1.setProperty("ca?uto", "\u20acuropeo");
165
		props1.setProperty("confli=cto", "amigo");
166
		props1.setProperty("  conflis =  :cto mayor ", " peque?o conflicto");
167
		props1.setProperty("abrir", "cerrar");
168
		props1.setProperty("puerta", "hembrilla");
169
		props1.setProperty("12libros", "quijote");
170
		initOutputStream();
171
		try {
172
			props1.store(os, "header", "UTF8");
173
		} catch (IOException e) {
174
			TestCase.fail(e.getLocalizedMessage());
175
		}
176
		
177
		// read file
178
		props2 = new OrderedProperties();
179
		initInputStream();
180
		try {
181
			props2.load(is, "UTF8");
182
		} catch (IOException e) {
183
			TestCase.fail(e.getLocalizedMessage());
184
		}
185
		// estos deber?an salir igual
186
		TestCase.assertEquals("hola", props2.getProperty("Prueba"));
187
		TestCase.assertEquals("holas", props2.getProperty("prueba2"));
188
		TestCase.assertEquals("cerrar", props2.getProperty("abrir"));
189
		TestCase.assertEquals("hembrilla", props2.getProperty("puerta"));
190
		TestCase.assertEquals("quijote", props2.getProperty("12libros"));
191
		// con estos en cambio no obtenemos los mismos valores que escribimos anteriormente. Es normal, porque incluimos
192
		// caracteres especiales como ":" y "=". Para manejarlos correctamente necesitamos usas los m?todos load/store
193
		// sin encoding, los cuales s? escapan los caracteres especiales
194
		TestCase.assertEquals("\u20acuropeo", props2.getProperty("ca?uto"));
195
		TestCase.assertEquals("cto=amigo", props2.getProperty("confli"));
196
		TestCase.assertEquals(":cto mayor = peque?o conflicto", props2.getProperty("conflis"));
197

  
198
		discardInputStream();
199
		discardOutputStream();
200
	}
201
	
202
}
0 203

  
tags/org.gvsig.desktop-2.0.131/org.gvsig.desktop.compat.cdc/org.gvsig.i18n/utils/test/src/org/gvsig/i18n/utils/TestUtils.java
1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.i18n.utils;
25

  
26
import java.io.File;
27
import java.io.IOException;
28

  
29
import junit.framework.TestCase;
30

  
31
/**
32
 * @author cesar
33
 *
34
 */
35
public class TestUtils extends TestCase {
36
	
37
	public ConfigOptions loadConfig() {
38
		ConfigOptions config = new ConfigOptions();
39
		config.setConfigFile("src-test"+File.separator+"org"+File.separator+"gvsig"+File.separator+"i18n"+File.separator+"utils"+File.separator+"config.xml");
40
		config.load();
41
		return config;
42
	}
43
	
44
	public void testConfigOptions() {
45
		ConfigOptions config = loadConfig();
46
		
47
		String databaseDir=null, basedir=null;
48
		try {
49
			databaseDir = new File("test-data/database").getCanonicalPath();
50
			basedir =  new File("test-data").getCanonicalPath();
51
		} catch (IOException e) {
52
			// TODO Auto-generated catch block
53
			e.printStackTrace();
54
		}
55
		
56
		// the values of the projects. They are pairs (dir, basename).
57
		String projectValues[]={"src/appgvSIG", "otro", "sources", "src/_fwAndami", "text", "sources"};
58
		for (int i=0; i<projectValues.length; i=i+3) {
59
			try {
60
				// set the canonical path
61
				projectValues[i]= new File(basedir+File.separator+projectValues[i]).getCanonicalPath();
62
			} catch (IOException e) {
63
				// TODO Auto-generated catch block
64
				e.printStackTrace();
65
			}
66
		}
67
		
68
		TestCase.assertEquals(databaseDir, config.databaseDir);
69
		TestCase.assertEquals(basedir, config.defaultBaseDir);
70
		TestCase.assertEquals("text", config.defaultBaseName);
71
		
72
		String languages = config.languages[0];
73
		for (int i=1; i<config.languages.length; i++) {
74
			languages=languages+";"+config.languages[i];
75
		}
76
		TestCase.assertEquals("ca;cs;de;en;es;eu;fr;gl;it;pt", languages);
77
		
78
		for (int i=0; i<config.projects.size(); i=i+3) {
79
			Project project = (Project) config.projects.get(i);
80
			TestCase.assertEquals(projectValues[i], project.dir);
81
			TestCase.assertEquals(projectValues[i+1], project.basename);
82
			TestCase.assertEquals(projectValues[i+2], project.sourceKeys);
83
		}
84
	}
85
	
86
	public void testTranslationDatabase() {
87
		ConfigOptions config = loadConfig();
88
		TranslationDatabase database = new TranslationDatabase(config);
89
		database.load();
90
		TestCase.assertEquals("A?adir Capa" , database.getTranslation("es", "Anadir_Capa"));
91
		TestCase.assertEquals("Add Layer" , database.getTranslation("en", "Anadir_Capa"));
92
		TestCase.assertEquals("Afegir Capa" , database.getTranslation("ca", "Anadir_Capa"));
93
		TestCase.assertEquals("Layer hinzuf?gen" , database.getTranslation("de", "Anadir_Capa"));
94
		TestCase.assertEquals("Ayuda" , database.getTranslation("es", "Ayuda"));
95
		TestCase.assertEquals(null , database.getTranslation("es", "test_case.clave_que_no_existe"));
96
		
97
		// add a translation
98
		database.setTranslation("es", "test_case.clave_que_no_existe", "Clave que no existe");
99
		// is it present now?
100
		TestCase.assertEquals("Clave que no existe" , database.getTranslation("es", "test_case.clave_que_no_existe"));
101
		
102
		// remove the translation
103
		database.removeTranslation("es", "test_case.clave_que_no_existe");
104
		// was really removed?
105
		TestCase.assertEquals(null , database.getTranslation("es", "test_case.clave_que_no_existe"));
106
		
107
		// add the translation again
108
		database.setTranslation("es", "test_case.clave_que_no_existe", "Clave que no existe");
109
		// save to disk
110
		database.save();
111
		// load from disk
112
		database.load();
113
		// is the translation still there?
114
		TestCase.assertEquals("Clave que no existe" , database.getTranslation("es", "test_case.clave_que_no_existe"));
115
		
116
		// remove the translation again and save to disk
117
		database.removeTranslation("es", "test_case.clave_que_no_existe");
118
		TestCase.assertEquals(null , database.getTranslation("es", "test_case.clave_que_no_existe"));
119
		TestCase.assertEquals("", database.getTranslation("es", "prueba"));
120
		database.save();
121
	}
122

  
123
	public void testKeys() {
124
		ConfigOptions config = loadConfig();
125
		Keys keys = new Keys(config);
126
		keys.load();
127
	}
128

  
129
}
0 130

  
tags/org.gvsig.desktop-2.0.131/org.gvsig.desktop.compat.cdc/org.gvsig.i18n/utils/test/src/org/gvsig/i18n/utils/config.xml
1
<?xml version="1.0" encoding="UTF-8"?>
2
<!--
3

  
4
    gvSIG. Desktop Geographic Information System.
5

  
6
    Copyright (C) 2007-2013 gvSIG Association.
7

  
8
    This program is free software; you can redistribute it and/or
9
    modify it under the terms of the GNU General Public License
10
    as published by the Free Software Foundation; either version 3
11
    of the License, or (at your option) any later version.
12

  
13
    This program is distributed in the hope that it will be useful,
14
    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
    GNU General Public License for more details.
17

  
18
    You should have received a copy of the GNU General Public License
19
    along with this program; if not, write to the Free Software
20
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21
    MA  02110-1301, USA.
22

  
23
    For any additional information, do not hesitate to contact us
24
    at info AT gvsig.com, or visit our website www.gvsig.com.
25

  
26
-->
27
<config>
28
	<!-- AquĆ­ especificamos algunas variables de configuraciĆ³n -->
29
	<!-- En este fichero se muestran todas las opciones posibles, en sus valores por defecto -->
30

  
31
	<!-- Nombre base por defecto de los ficheros con las traducciones. En nuestro caso suele ser "text",
32
		de forma que los ficheros toman nombres como "text.properties", "text_en.properties". NĆ³tese
33
		que sĆ³lo es el nombre por defecto. Cada proyecto puede especificar un baseName distinto -->
34
	<variable name="basename" value="text" />
35

  
36
	<!-- Directorio base. Las rutas relativas especificadas en otras variables (databaseDir, directorios
37
		de proyecto) tomarƔn este directorio como directorio base.  Por defecto es el directorio
38
		desde el que se llama a la aplicaciĆ³n -->
39
	<variable name="basedir" value="test-data" />
40

  
41
	<!-- Lista de idiomas que se tendrƔn en cuenta  -->
42
	<variable name="languages" value="ca;cs;de;en;es;eu;fr;gl;it;pt" />
43
	
44
	<!-- El directorio que contendrĆ” la base de datos de traducciones por idioma. Por defecto es el
45
		directorio "database", relativo al directorio especificado en la variable "basedir".  -->
46
	<variable name="databaseDir" value="database" />
47
	
48
		<!-- El directorio por defecto que contendrĆ” los property files que almacenan las claves de cada
49
	 proyecto". Esto se usa en los proyectos que no especifican un atributo "propertyDir". Si el
50
	 directorio no es absoluto, entonces es relativo al directorio de cada proyecto. -->
51
	<variable name="defaultPropertyDir" value="config" />
52
	
53
	<variable name="sourceKeys" value="sources" />
54
</config>
55
<projects>
56
	<!-- Los proyectos que se van a leer. Es necesario especificar un directorio (relativo o absoluto),
57
		y opcionalmente se puede incluir un atributo "basename" para especificar un nombre base
58
		distinto del nombre base por defecto -->
59
	<!-- The projects which are going to be read. An absolute or relative directory name must be specified,
60
		in which the property files are located. An optional "basename" attribute is also accepted,
61
		to override the default basename -->
62
	<project dir="src/appgvSIG" basename="otro"  sourceKeys="sources" propertyDir="config" />
63
	<project dir="src/_fwAndami" />
64
</projects>
0 65

  
tags/org.gvsig.desktop-2.0.131/org.gvsig.desktop.compat.cdc/org.gvsig.i18n/utils/java/src/org/gvsig/i18n/utils/ConfigOptions.java
1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.i18n.utils;
25

  
26
import java.io.File;
27
import java.io.FileInputStream;
28
import java.io.FileNotFoundException;
29
import java.io.IOException;
30
import java.util.ArrayList;
31

  
32
import org.kxml2.io.KXmlParser;
33
import org.xmlpull.v1.XmlPullParserException;
34

  
35
public class ConfigOptions {
36
	// Default values
37
	public String defaultBaseName = "text";
38
	public String defaultBaseDir = ".";
39
	public String databaseDir = "database";
40
	private String configFileName = "config.xml";
41
	public String[] languages;
42
	public ArrayList projects = new ArrayList();
43
	private String defaultLangList="ca;cs;de;en;es;eu;fr;gl;it;pt";
44
	public String sourceKeys = "sources";
45
	private String defaultPropertyDir = "config";
46
	public String[] outputLanguages={"en", "es"};
47
	public String outputDir="output";
48
	public String inputDir="input";
49
	public String[] defaultSrcDirs={"src"};
50
	
51
	
52
	/**
53
	 * The character encoding of the Java source files, used to search keys in the sources.
54
	 */
55
	public String sourcesEncoding = "ISO8859_1";
56
	/**
57
	 * The character encoding of the generated output files for missing keys.
58
	 */
59
	public String outputEncoding = "UTF8";
60
	
61
	/**
62
	 * Creates a new ConfigOptions object.
63
	 */
64
	public ConfigOptions() {
65
		// Now we transform all directories to absolute canonical paths, so
66
		// that the are easier to manage afterwards.
67
		// It's also done at the end of parseVars method, but we must also do
68
		// it here, because parseVars() might not get executed.
69
		try {
70
			this.defaultBaseDir = getAbsolutePath(".", this.defaultBaseDir);
71
			this.databaseDir = getAbsolutePath(this.defaultBaseDir, this.databaseDir);
72
			this.outputDir = getAbsolutePath(this.defaultBaseDir, this.outputDir);
73
			this.inputDir = getAbsolutePath(this.defaultBaseDir, this.inputDir);
74
			
75
			/*
76
			 * 
77
			 File baseDirFile = new File(this.defaultBaseDir);
78
			this.defaultBaseDir = baseDirFile.getCanonicalPath();
79
			File databaseDirFile = new File(this.databaseDir);
80
			if (databaseDirFile.isAbsolute()) {
81
				this.databaseDir = databaseDirFile.getCanonicalPath();
82
			}
83
			else {
84
				this.databaseDir = (new File(this.defaultBaseDir+File.separator+this.databaseDir)).getCanonicalPath();
85
			}
86
			File outputDirFile = new File(this.outputDir);
87
			if (outputDirFile.isAbsolute()) {
88
				this.outputDir = outputDirFile.getCanonicalPath();
89
			}
90
			else {
91
				this.outputDir = (new File(this.defaultBaseDir+File.separator+this.outputDir)).getCanonicalPath();
92
			}
93
			File inputDirFile = new File(this.inputDir);
94
			if (inputDirFile.isAbsolute()) {
95
				this.inputDir = inputDirFile.getCanonicalPath();
96
			}
97
			else {
98
				this.inputDir = (new File(this.defaultBaseDir+File.separator+this.inputDir)).getCanonicalPath();
99
			}
100
			*/
101
		} catch (IOException e) {
102
			System.err.println("Error accediendo a los directorios de las traducciones: "+e.getLocalizedMessage());
103
		}
104
	}
105
	
106
	/**
107
	 *  Creates a new ConfigOptions object, defining the config file to use.
108
	 *  
109
	 * @param configFileName The file name of the config file to use.
110
	 */
111
	public ConfigOptions(String configFileName) {
112
		this.configFileName = configFileName;
113
		
114
		// Now we transform all directories to absolute canonical paths, so
115
		// that the are easier to manage afterwards.
116
		// It's also done at the end of parseVars method, but we must also do
117
		// it here, because parseVars() might not get executed.
118
		try {
119
			this.defaultBaseDir = getAbsolutePath(".", this.defaultBaseDir);
120
			this.databaseDir = getAbsolutePath(this.defaultBaseDir, this.databaseDir);
121
			this.outputDir = getAbsolutePath(this.defaultBaseDir, this.outputDir);
122
			this.inputDir = getAbsolutePath(this.defaultBaseDir, this.inputDir);
123
			
124
			/*File baseDirFile = new File(this.defaultBaseDir);
125
			this.defaultBaseDir = baseDirFile.getCanonicalPath();
126
			File databaseDirFile = new File(this.databaseDir);
127
			if (databaseDirFile.isAbsolute()) {
128
				this.databaseDir = databaseDirFile.getCanonicalPath();
129
			}
130
			else {
131
				this.databaseDir = (new File(this.defaultBaseDir+File.separator+this.databaseDir)).getCanonicalPath();
132
			}
133
			File outputDirFile = new File(this.outputDir);
134
			if (outputDirFile.isAbsolute()) {
135
				this.outputDir = outputDirFile.getCanonicalPath();
136
			}
137
			else {
138
				this.outputDir = (new File(this.defaultBaseDir+File.separator+this.outputDir)).getCanonicalPath();
139
			}
140
			File inputDirFile = new File(this.inputDir);
141
			if (inputDirFile.isAbsolute()) {
142
				this.inputDir = inputDirFile.getCanonicalPath();
143
			}
144
			else {
145
				this.inputDir = (new File(this.defaultBaseDir+File.separator+this.inputDir)).getCanonicalPath();
146
			}*/
147
		} catch (IOException e) {
148
			System.err.println("Error accediendo a los directorios de las traducciones: "+e.getLocalizedMessage());
149
		}
150
	}
151
	
152
	/**
153
	 * Sets the name of the config file to use.
154
	 * 
155
	 * @param configFileName
156
	 */
157
	public void setConfigFile(String configFileName) {
158
		this.configFileName = configFileName;
159
	}
160
	
161
	/**
162
	 * Gets the name of the config file in use.
163
	 * 
164
	 * @return The name of the config file in use.
165
	 */
166
	public String getConfigFile() {
167
		return configFileName;
168
	}
169
	
170
	/**
171
	 *  Loads the config parameters and the projects to consider from the XML
172
	 * config file */
173
	public boolean load() {
174
		KXmlParser parser = new KXmlParser();
175
		
176
		// we use null encoding, in this way kxml2 tries to detect the encoding
177
		try {
178
			parser.setInput(new FileInputStream(configFileName), null);
179
		} catch (FileNotFoundException e1) {
180
			System.err.println(e1.getLocalizedMessage());
181
			return false;
182
		} catch (XmlPullParserException e1) {
183
			// No podemos leer el fichero de configuraci?n. Usamos valores por defecto
184
			System.err.println("Aviso: no se pudo leer correctamente el fichero de configuraci?n. Se usar?n los valores por defecto.");
185
			return false;
186
		}
187
		
188
		try {
189
			for (parser.next(); parser.getEventType()!=KXmlParser.END_DOCUMENT; parser.next()) {
190
				// este bucle externo recorre las etiquetas de primer y segundo nivel
191
				if (parser.getEventType()==KXmlParser.START_TAG) {
192
					if (parser.getName().equals("config")) {
193
						parseVars(parser);
194
					}
195
					else if (parser.getName().equals("projects")) {
196
						parseProjects(parser);
197
					}
198
				}
199
			}	
200
		} catch (XmlPullParserException e1) {
201
			e1.getLocalizedMessage();
202
		} catch (IOException e1) {
203
			e1.getLocalizedMessage();
204
		}
205
		
206
		File outputDirFile = new File(outputDir);
207
		outputDirFile.mkdirs();
208
		File databaseDirFile = new File(databaseDir);
209
		databaseDirFile.mkdirs();
210
		return true;
211
	}
212

  
213
	private void parseVars(KXmlParser parser) throws XmlPullParserException, IOException {
214
		// recorremos todas las etiquetas 'variable' dentro de config
215
		int state;
216
		String name, value;
217
		
218
		for (state = parser.next(); state!=KXmlParser.END_TAG || !parser.getName().equals("config") ; state=parser.next()) {
219
			if (state==KXmlParser.START_TAG) {
220
				if (parser.getName().equals("variable")) {
221
					name = parser.getAttributeValue(null, "name");
222
					value = parser.getAttributeValue(null, "value");
223
					if (name!=null && value!=null) {
224
						value = parser.getAttributeValue(null, "value");
225
						if (parser.getAttributeValue(null, "name").equals("basename")) {
226
							defaultBaseName = parser.getAttributeValue(null, "value");
227
						}
228
						else if (parser.getAttributeValue(null, "name").equals("basedir")) {
229
							defaultBaseDir = parser.getAttributeValue(null, "value");
230
						}
231
						else if (parser.getAttributeValue(null, "name").equals("databaseDir")) {
232
							databaseDir = parser.getAttributeValue(null, "value");
233
						}
234
						else if (parser.getAttributeValue(null, "name").equals("defaultPropertyDir")) {
235
							defaultPropertyDir = parser.getAttributeValue(null, "value");
236
						}
237
						else if (parser.getAttributeValue(null, "name").equals("outputDir")) {
238
							outputDir = parser.getAttributeValue(null, "value");
239
						}
240
						else if (parser.getAttributeValue(null, "name").equals("inputDir")) {
241
							inputDir = parser.getAttributeValue(null, "value");
242
						}
243
						else if (parser.getAttributeValue(null, "name").equals("sourceKeys")) {
244
							sourceKeys = parser.getAttributeValue(null, "value");
245
						}
246
						else if (parser.getAttributeValue(null, "name").equals("srcDirs")) {
247
							String srcDirs = parser.getAttributeValue(null, "value");
248
							this.defaultSrcDirs = srcDirs.split(";");
249
						}
250
						else if (parser.getAttributeValue(null, "name").equals("languages")) {
251
							languages = parser.getAttributeValue(null, "value").split(";");
252
							if (languages.length==0) {
253
								System.err.println("Aviso: No se definieron idiomas a considerar. Se usar? la lista de idiomas\n por defecto: "+defaultLangList);
254
								languages = defaultLangList.split(";");
255
							}
256
						}
257
					}
258
					else {
259
						if (name==null)
260
							System.err.println("Error leyendo el fichero de configuraci?n. No se encontr? el atributo 'name'\nrequerido en la etiqueta <variable>. La etiqueta ser? ignorada.");
261
						if (value==null)
262
							System.err.println("Error leyendo el fichero de configuraci?n. No se encontr? el atributo 'value'\nrequerido en la etiqueta <variable>. La etiqueta ser? ignorada.");
263
					}
264
				}
265
				else {
266
					System.err.println("Aviso: se ignor? una etiqueta desconocida o inesperada: " + parser.getName());
267
				}
268
			}
269
		}
270
		
271
		// Now we transform all directories to absolute canonical paths, so
272
		// that they are easier to manage afterwards.
273
		try {
274
			this.defaultBaseDir = getAbsolutePath(".", this.defaultBaseDir);
275
			this.databaseDir = getAbsolutePath(this.defaultBaseDir, this.databaseDir);
276
			this.outputDir = getAbsolutePath(this.defaultBaseDir, this.outputDir);
277
			this.inputDir = getAbsolutePath(this.defaultBaseDir, this.inputDir);
278
			/**
279
			File baseDirFile = new File(this.defaultBaseDir);
280
			this.defaultBaseDir = baseDirFile.getCanonicalPath();
281
			System.out.println(this.defaultBaseDir);
282
			File databaseDirFile = new File(this.databaseDir);
283
			if (databaseDirFile.isAbsolute()) {
284
				this.databaseDir = databaseDirFile.getCanonicalPath();
285
			}
286
			else {
287
				this.databaseDir = (new File(this.defaultBaseDir+File.separator+this.databaseDir)).getCanonicalPath();
288
			}
289
			File outputDirFile = new File(this.outputDir);
290
			if (outputDirFile.isAbsolute()) {
291
				this.outputDir = outputDirFile.getCanonicalPath();
292
			}
293
			else {
294
				this.outputDir = (new File(this.defaultBaseDir+File.separator+this.outputDir)).getCanonicalPath();
295
			}
296
			File inputDirFile = new File(this.inputDir);
297
			if (inputDirFile.isAbsolute()) {
298
				this.inputDir = inputDirFile.getCanonicalPath();
299
			}
300
			else {
301
				this.inputDir = (new File(this.defaultBaseDir+File.separator+this.inputDir)).getCanonicalPath();
302
			}
303
			*/
304
		} catch (IOException e) {
305
			System.err.println("Error accediendo a los directorios de las traducciones: "+e.getLocalizedMessage());
306
		}
307
	}
308
	
309
	/**
310
	 * Parse the lines containing <project /> tags (between <projects> and </projects>).
311
	 * 
312
	 * @param parser The KXmlParser, pointing to the next <project /> tag (if any)
313
	 * @throws XmlPullParserException
314
	 * @throws IOException
315
	 */
316
	private void parseProjects(KXmlParser parser) throws XmlPullParserException, IOException {
317
		// recorremos todos los proyectos dentro de 'projects'
318
		int state;
319
		String dir;
320
		File dirFile;
321
		Project project;
322
		
323
		for (state = parser.next(); state!=KXmlParser.END_TAG || !parser.getName().equals("projects") ; state=parser.next()) {
324
			if (state==KXmlParser.START_TAG) {
325
				if (parser.getName().equals("project")) {
326
					if (parser.getAttributeValue(null, "dir")!=null) {
327
						dir = parser.getAttributeValue(null,  "dir");
328
						if (dir!=null) {
329
							// we transform it to absolute canonical paths, so
330
							// that it is easier to manage afterwards.
331
							dirFile = new File(dir);
332
							try {
333
								if (dirFile.isAbsolute()) {
334
									dir = dirFile.getCanonicalPath();
335
								}
336
								else {
337
									dir = new File(this.defaultBaseDir+File.separator+dir).getCanonicalPath();
338
								}
339
							} catch (IOException e) {
340
								System.err.println("Error accediendo a los directorios de las traducciones: "+e.getLocalizedMessage());
341
							}
342
							project = new Project();
343
							project.dir = dir;
344
							project.basename = parser.getAttributeValue(null, "basename");
345
							if (project.basename==null)
346
								project.basename = this.defaultBaseName;
347
							
348
							project.propertyDir = parser.getAttributeValue(null, "propertyDir");
349
							if (project.propertyDir==null) {
350
								project.propertyDir = this.defaultPropertyDir;
351
							}
352
							// we transform it to absolute canonical paths, so
353
							// that it is easier to manage afterwards.
354
							File propDirFile = new File(project.propertyDir);
355
							try {
356
								if (propDirFile.isAbsolute()) {
357
									project.propertyDir = propDirFile.getCanonicalPath();
358
								}
359
								else {
360
									project.propertyDir = new File(dir+File.separator+project.propertyDir).getCanonicalPath();
361
								}
362
							} catch (IOException e) {
363
								System.err.println("Error accediendo a los directorios de las traducciones: "+e.getLocalizedMessage());
364
							}
365

  
366
							String srcDirs = parser.getAttributeValue(null, "srcDirs");
367
							if (srcDirs!=null) {
368
								project.srcDirs = srcDirs.split(";");
369
							}
370
							else {
371
								project.srcDirs = this.defaultSrcDirs;
372
							}
373

  
374
							project.sourceKeys = parser.getAttributeValue(null, "sourceKeys");
375
							if (project.sourceKeys==null)
376
								project.sourceKeys = this.sourceKeys;
377
							projects.add(project);
378
						}
379
						else
380
							System.err.println("Error leyendo el fichero de configuraci?n. No se encontr? el atributo 'dir'\nrequerido en la etiqueta <project>. La etiqueta ser? ignorada.");
381
					}
382
				}
383
				else {
384
					System.err.println("Aviso: se ignorar? una etiqueta desconocida o inesperada: " + parser.getName());
385
				}
386
			}
387
		}
388

  
389
	}
390
	
391
	public void setLanguages(String[] languages) {
392
		this.languages = languages; 
393
	}
394
	
395
	public void setProjects(ArrayList projectList) {
396
		this.projects = projectList;
397
	}
398
	
399
	/**
400
	 * Calculates the canonical path for the given path.
401
	 * If the given path is relative, it is calculated from
402
	 * the given baseDir.
403
	 * The 'path' parameter uses the '/' character to as path
404
	 * separator. The returned value uses the default system
405
	 * separator as path separator.  
406
	 * 
407
	 * @param baseDir
408
	 * @param path
409
	 * @return
410
	 * @throws IOException 
411
	 */
412
	public static String getAbsolutePath(String baseDir, String path) throws IOException {
413
		if ('/'!=File.separatorChar)
414
			path = path.replace('/', File.separatorChar);
415
		File pathFile = new File(path);
416
		if (pathFile.isAbsolute())
417
			path = pathFile.getCanonicalPath();
418
		else {
419
			File newFile = new File(baseDir+File.separator+path);
420
			path = newFile.getAbsolutePath();
421
		}
422
		return path;
423
	}
424
}
0 425

  
tags/org.gvsig.desktop-2.0.131/org.gvsig.desktop.compat.cdc/org.gvsig.i18n/utils/java/src/org/gvsig/i18n/utils/OrderedProperties.java
1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24

  
25
package org.gvsig.i18n.utils;
26

  
27
import java.io.BufferedReader;
28
import java.io.IOException;
29
import java.io.InputStream;
30
import java.io.InputStreamReader;
31
import java.io.OutputStream;
32
import java.io.OutputStreamWriter;
33
import java.io.PrintStream;
34
import java.io.PrintWriter;
35
import java.util.Calendar;
36
import java.util.Collections;
37
import java.util.Comparator;
38
import java.util.Enumeration;
39
import java.util.HashSet;
40
import java.util.Iterator;
41
import java.util.PropertyResourceBundle;
42
import java.util.Set;
43
import java.util.TreeMap;
44
import java.util.Map.Entry;
45

  
46
/**
47
* A set of persistent properties, which can be saved or loaded from a stream.
48
* A property list may also contain defaults, searched if the main list
49
* does not contain a property for a given key.
50
*
51
* An example of a properties file for the german language is given
52
* here.  This extends the example given in ListResourceBundle.
53
* Create a file MyResource_de.properties with the following contents
54
* and put it in the CLASSPATH.  (The character
55
* <code>\</code><code>u00e4</code> is the german umlaut)
56
*
57
* 
58
<pre>s1=3
59
s2=MeineDisk
60
s3=3. M\<code></code>u00e4rz 96
61
s4=Die Diskette ''{1}'' enth\<code></code>u00e4lt {0} in {2}.
62
s5=0
63
s6=keine Dateien
64
s7=1
65
s8=eine Datei
66
s9=2
67
s10={0,number} Dateien
68
s11=Das Formatieren schlug fehl mit folgender Exception: {0}
69
s12=FEHLER
70
s13=Ergebnis
71
s14=Dialog
72
s15=Auswahlkriterium
73
s16=1,3</pre>
74
*
75
* <p>Although this is a sub class of a hash table, you should never
76
* insert anything other than strings to this property, or several
77
* methods, that need string keys and values, will fail.  To ensure
78
* this, you should use the <code>get/setProperty</code> method instead
79
* of <code>get/put</code>.
80
*
81
* Properties are saved in the specified encoding. If no encoding is
82
* specified, then the ISO 8859-1 encoding is used, with Unicode escapes with
83
* a single <code>u</code> for any character which cannot be represented.
84
*
85
* @author Jochen Hoenicke
86
* @author Eric Blake (ebb9@email.byu.edu)
87
* @author Cesar Martinez Izquierdo (cesar.martinez@iver.es)
88
* @see PropertyResourceBundle
89
* @status updated to 1.4
90
*/
91
public class OrderedProperties extends TreeMap
92
{
93
	
94
/**
95
* The property list that contains default values for any keys not
96
* in this property list.
97
*
98
* @serial the default properties
99
*/
100
protected OrderedProperties defaults;
101

  
102
/**
103
* Compatible with JDK 1.0+.
104
*/
105
private static final long serialVersionUID = -5087876565919950510L;
106

  
107
/**
108
* Creates a new empty property list with no default values.
109
*/
110
public OrderedProperties()
111
{
112
	super(new StringComparator());
113
}
114

  
115
/**
116
* Create a new empty property list with the specified default values.
117
*
118
* @param defaults a Properties object containing the default values
119
*/
120
public OrderedProperties(OrderedProperties defaults)
121
{
122
	super(new StringComparator());
123
	this.defaults = defaults;
124
}
125

  
126
/**
127
* Adds the given key/value pair to this properties.  This calls
128
* the hashtable method put.
129
*
130
* @param key the key for this property
131
* @param value the value for this property
132
* @return The old value for the given key
133
* @see #getProperty(String)
134
* @since 1.2
135
*/
136
public Object setProperty(String key, String value)
137
{
138
 return put(key, value);
139
}
140

  
141
/**
142
* Reads a property list from an input stream.  The stream should
143
* have the following format: <br>
144
*
145
* An empty line or a line starting with <code>#</code> or
146
* <code>!</code> is ignored.  An backslash (<code>\</code>) at the
147
* end of the line makes the line continueing on the next line
148
* (but make sure there is no whitespace after the backslash).
149
* Otherwise, each line describes a key/value pair. <br>
150
*
151
* The chars up to the first whitespace, = or : are the key.  You
152
* can include these caracters in the key, if you precede them with
153
* a backslash (<code>\</code>). The key is followed by optional
154
* whitespaces, optionally one <code>=</code> or <code>:</code>,
155
* and optionally some more whitespaces.  The rest of the line is
156
* the resource belonging to the key. <br>
157
*
158
* Escape sequences <code>\t, \n, \r, \\, \", \', \!, \#, \ </code>(a
159
* space), and unicode characters with the
160
* <code>\\u</code><em>xxxx</em> notation are detected, and
161
* converted to the corresponding single character. <br>
162
*
163
* 
164
<pre># This is a comment
165
key     = value
166
k\:5      \ a string starting with space and ending with newline\n
167
# This is a multiline specification; note that the value contains
168
# no white space.
169
weekdays: Sunday,Monday,Tuesday,Wednesday,\\
170
       Thursday,Friday,Saturday
171
# The safest way to include a space at the end of a value:
172
label   = Name:\\u0020</pre>
173
*
174
* @param inStream the input stream
175
* @throws IOException if an error occurred when reading the input
176
* @throws NullPointerException if in is null
177
*/
178
public void load(InputStream inStream) throws IOException
179
{
180
 // The spec says that the file must be encoded using ISO-8859-1.
181
 BufferedReader reader =
182
   new BufferedReader(new InputStreamReader(inStream, "ISO-8859-1"));
183
 String line;
184

  
185
 while ((line = reader.readLine()) != null)
186
   {
187
     char c = 0;
188
     int pos = 0;
189
	// Leading whitespaces must be deleted first.
190
     while (pos < line.length()
191
            && Character.isWhitespace(c = line.charAt(pos)))
192
       pos++;
193

  
194
     // If empty line or begins with a comment character, skip this line.
195
     if ((line.length() - pos) == 0
196
	    || line.charAt(pos) == '#' || line.charAt(pos) == '!')
197
       continue;
198

  
199
     // The characters up to the next Whitespace, ':', or '='
200
     // describe the key.  But look for escape sequences.
201
	// Try to short-circuit when there is no escape char.
202
	int start = pos;
203
	boolean needsEscape = line.indexOf('\\', pos) != -1;
204
     StringBuffer key = needsEscape ? new StringBuffer() : null;
205
     while (pos < line.length()
206
            && ! Character.isWhitespace(c = line.charAt(pos++))
207
            && c != '=' && c != ':')
208
       {
209
         if (needsEscape && c == '\\')
210
           {
211
             if (pos == line.length())
212
               {
213
                 // The line continues on the next line.  If there
214
                 // is no next line, just treat it as a key with an
215
                 // empty value.
216
                 line = reader.readLine();
217
		    if (line == null)
218
		      line = "";
219
                 pos = 0;
220
                 while (pos < line.length()
221
                        && Character.isWhitespace(c = line.charAt(pos)))
222
                   pos++;
223
               }
224
             else
225
               {
226
                 c = line.charAt(pos++);
227
                 switch (c)
228
                   {
229
                   case 'n':
230
                     key.append('\n');
231
                     break;
232
                   case 't':
233
                     key.append('\t');
234
                     break;
235
                   case 'r':
236
                     key.append('\r');
237
                     break;
238
                   case 'u':
239
                     if (pos + 4 <= line.length())
240
                       {
241
                         char uni = (char) Integer.parseInt
242
                           (line.substring(pos, pos + 4), 16);
243
                         key.append(uni);
244
                         pos += 4;
245
                       }        // else throw exception?
246
                     break;
247
                   default:
248
                     key.append(c);
249
                     break;
250
                   }
251
               }
252
           }
253
         else if (needsEscape)
254
           key.append(c);
255
       }
256

  
257
     boolean isDelim = (c == ':' || c == '=');
258

  
259
	String keyString;
260
	if (needsEscape)
261
	  keyString = key.toString();
262
	else if (isDelim || Character.isWhitespace(c))
263
	  keyString = line.substring(start, pos - 1);
264
	else
265
	  keyString = line.substring(start, pos);
266

  
267
     while (pos < line.length()
268
            && Character.isWhitespace(c = line.charAt(pos)))
269
       pos++;
270

  
271
     if (! isDelim && (c == ':' || c == '='))
272
       {
273
         pos++;
274
         while (pos < line.length()
275
                && Character.isWhitespace(c = line.charAt(pos)))
276
           pos++;
277
       }
278

  
279
	// Short-circuit if no escape chars found.
280
	if (!needsEscape)
281
	  {
282
	    put(keyString, line.substring(pos));
283
	    continue;
284
	  }
285

  
286
	// Escape char found so iterate through the rest of the line.
287
     StringBuffer element = new StringBuffer(line.length() - pos);
288
     while (pos < line.length())
289
       {
290
         c = line.charAt(pos++);
291
         if (c == '\\')
292
           {
293
             if (pos == line.length())
294
               {
295
                 // The line continues on the next line.
296
                 line = reader.readLine();
297

  
298
		    // We might have seen a backslash at the end of
299
		    // the file.  The JDK ignores the backslash in
300
		    // this case, so we follow for compatibility.
301
		    if (line == null)
302
		      break;
303

  
304
                 pos = 0;
305
                 while (pos < line.length()
306
                        && Character.isWhitespace(c = line.charAt(pos)))
307
                   pos++;
308
                 element.ensureCapacity(line.length() - pos +
309
                                        element.length());
310
               }
311
             else
312
               {
313
                 c = line.charAt(pos++);
314
                 switch (c)
315
                   {
316
                   case 'n':
317
                     element.append('\n');
318
                     break;
319
                   case 't':
320
                     element.append('\t');
321
                     break;
322
                   case 'r':
323
                     element.append('\r');
324
                     break;
325
                   case 'u':
326
                     if (pos + 4 <= line.length())
327
                       {
328
                         char uni = (char) Integer.parseInt
329
                           (line.substring(pos, pos + 4), 16);
330
                         element.append(uni);
331
                         pos += 4;
332
                       }        // else throw exception?
333
                     break;
334
                   default:
335
                     element.append(c);
336
                     break;
337
                   }
338
               }
339
           }
340
         else
341
           element.append(c);
342
       }
343
     put(keyString, element.toString());
344
   }
345
}
346

  
347
/**
348
* Reads a property list from an input stream, using the
349
* provided encoding. The provided stream should be
350
* correctly encoded as specified, otherwise an IOException
351
* error will be thrown. No escape sequences are accepted
352
* to represent any character, and thus this method has some
353
* limitations and the
354
* format of the accepted property files is slightly
355
* different from
356
* the standard Java property files.
357
* 
358
* The main differences are:
359
* <ul><li>whitespaces, = or : cannot be present in
360
* the key.</li>
361
* <li>each pair key/value must be contained in a single line</li>
362
* </ul>
363
* 
364
* The stream should have the following format: <br>
365
*
366
* An empty line or a line starting with <code>#</code> or
367
* <code>!</code> is ignored.
368
* Otherwise, each line describes a key/value pair. <br>
369
*
370
* The chars up to the first whitespace, = or : are the key.  You
371
* cannot include these caracters in the key. The key is followed by optional
372
* whitespaces, optionally one <code>=</code> or <code>:</code>,
373
* and optionally some more whitespaces.  The rest of the line is
374
* the resource belonging to the key. <br>
375
*
376
* @param inStream the input stream
377
* @throws IOException if an error occurred when reading the input
378
* @throws NullPointerException if in is null
379
*/
380
public void load(InputStream inStream, String encoding) throws IOException {
381
	BufferedReader reader = new BufferedReader(new InputStreamReader(inStream, encoding));
382

  
383
	String line;
384
	while ((line = reader.readLine()) != null) {
385
		int pos = 0;
386
		// Leading whitespaces must be deleted first.
387
		while (pos < line.length()
388
			 && Character.isWhitespace(line.charAt(pos)))
389
			pos++;
390

  
391
     	// If empty line or begins with a comment character, skip this line.
392
     	if ((line.length() - pos) == 0
393
     			|| line.charAt(pos) == '#' || line.charAt(pos) == '!')
394
     		continue;
395

  
396

  
397
     	// do something
398
     	String[] entry = line.substring(pos).split(" *[=: ] *", 2);
399
     	if (entry.length==2) {
400
     		put(entry[0], entry[1]);
401
     	}
402
     	else {
403
     		put(entry[0], "");
404
     	}
405
	}
406
}
407

  
408

  
409
/**
410
* Writes the key/value pairs to the given output stream, in a format
411
* suitable for
412
* {@link #load(InputStream, String) load(InputStream is, String encoding)}.
413
* Note that this method does not use escape sequences to represent
414
* characters outside the encoding range, charset-dependent
415
* substitution sequence will
416
* be generated if such character is present in the stream.
417
* Moreover, because there is no escape sequences, the newline (\n)
418
* and carriage return (\r) characters must not be used (the 
419
* resulting property file will be incorrect). Because of the
420
* same reason, whitespaces, :, =, ! and # must not be used in the
421
* key<br>
422
*
423
* If header is not null, this method writes a comment containing
424
* the header as first line to the stream.  The next line (or first
425
* line if header is null) contains a comment with the current date.
426
* Afterwards the key/value pairs are written to the stream in the
427
* following format.<br>
428
*
429
* Each line has the form <code>key = value</code>.
430
*
431
* Following the listing, the output stream is flushed but left open.
432
*
433
* @param out the output stream
434
* @param header the header written in the first line, may be null
435
* @throws ClassCastException if this property contains any key or
436
*         value that isn't a string
437
* @throws IOException if writing to the stream fails
438
* @throws NullPointerException if out is null
439
* @since 1.2
440
*/
441
public void store(OutputStream out, String header, String encoding) throws IOException {
442
	PrintWriter writer
443
	   = new PrintWriter(new OutputStreamWriter(out, encoding));
444
	if (header != null)
445
		writer.println("#" + header);
446
	writer.println ("#" + Calendar.getInstance ().getTime ());
447

  
448
	Iterator iter = entrySet ().iterator ();
449
	int i = size ();
450
	while (--i >= 0) {
451
		Entry entry = (Entry) iter.next ();
452
	    writer.println (entry.getKey()+"="+entry.getValue());
453
	}
454

  
455
	writer.flush ();
456
}
457

  
458

  
459

  
460
/**
461
* Writes the key/value pairs to the given output stream, in a format
462
* suitable for {@link #load(InputStream) load(InputStream)}.<br>
463
*
464
* If header is not null, this method writes a comment containing
465
* the header as first line to the stream.  The next line (or first
466
* line if header is null) contains a comment with the current date.
467
* Afterwards the key/value pairs are written to the stream in the
468
* following format.<br>
469
*
470
* Each line has the form <code>key = value</code>.  Newlines,
471
* Returns and tabs are written as <code>\n,\t,\r</code> resp.
472
* The characters <code>\, !, #, =</code> and <code>:</code> are
473
* preceeded by a backslash.  Spaces are preceded with a backslash,
474
* if and only if they are at the beginning of the key.  Characters
475
* that are not in the ascii range 33 to 127 are written in the
476
* <code>\</code><code>u</code>xxxx Form.<br>
477
*
478
* Following the listing, the output stream is flushed but left open.
479
*
480
* @param out the output stream
481
* @param header the header written in the first line, may be null
482
* @throws ClassCastException if this property contains any key or
483
*         value that isn't a string
484
* @throws IOException if writing to the stream fails
485
* @throws NullPointerException if out is null
486
* @since 1.2
487
*/
488
public void store(OutputStream out, String header) throws IOException
489
{
490
 // The spec says that the file must be encoded using ISO-8859-1.
491
 PrintWriter writer
492
   = new PrintWriter(new OutputStreamWriter(out, "ISO-8859-1"));
493
 if (header != null)
494
   writer.println("#" + header);
495
 writer.println ("#" + Calendar.getInstance ().getTime ());
496
 
497
 Iterator iter = entrySet ().iterator ();
498
 int i = size ();
499
 StringBuffer s = new StringBuffer (); // Reuse the same buffer.
500
 while (--i >= 0)
501
   {
502
     Entry entry = (Entry) iter.next ();
503
     formatForOutput ((String) entry.getKey (), s, true);
504
     s.append ('=');
505
     formatForOutput ((String) entry.getValue (), s, false);
506
     writer.println (s);
507
   }
508

  
509
 writer.flush ();
510
}
511

  
512
/**
513
* Gets the property with the specified key in this property list.
514
* If the key is not found, the default property list is searched.
515
* If the property is not found in the default, null is returned.
516
*
517
* @param key The key for this property
518
* @return the value for the given key, or null if not found
519
* @throws ClassCastException if this property contains any key or
520
*         value that isn't a string
521
* @see #defaults
522
* @see #setProperty(String, String)
523
* @see #getProperty(String, String)
524
*/
525
public String getProperty(String key)
526
{
527
 OrderedProperties prop = this;
528
 // Eliminate tail recursion.
529
 do
530
   {
531
     String value = (String) prop.get(key);
532
     if (value != null)
533
       return value;
534
     prop = prop.defaults;
535
   }
536
 while (prop != null);
537
 return null;
538
}
539

  
540
/**
541
* Gets the property with the specified key in this property list.  If
542
* the key is not found, the default property list is searched.  If the
543
* property is not found in the default, the specified defaultValue is
544
* returned.
545
*
546
* @param key The key for this property
547
* @param defaultValue A default value
548
* @return The value for the given key
549
* @throws ClassCastException if this property contains any key or
550
*         value that isn't a string
551
* @see #defaults
552
* @see #setProperty(String, String)
553
*/
554
public String getProperty(String key, String defaultValue)
555
{
556
 String prop = getProperty(key);
557
 if (prop == null)
558
   prop = defaultValue;
559
 return prop;
560
}
561

  
562
/**
563
* Returns an enumeration of all keys in this property list, including
564
* the keys in the default property list.
565
*
566
* @return an Enumeration of all defined keys
567
*/
568
public Enumeration propertyNames()
569
{
570
 // We make a new Set that holds all the keys, then return an enumeration
571
 // for that. This prevents modifications from ruining the enumeration,
572
 // as well as ignoring duplicates.
573
 OrderedProperties prop = this;
574
 Set s = new HashSet();
575
 // Eliminate tail recursion.
576
 do
577
   {
578
     s.addAll(prop.keySet());
579
     prop = prop.defaults;
580
   }
581
 while (prop != null);
582
 return Collections.enumeration(s);
583
}
584

  
585
/**
586
* Prints the key/value pairs to the given print stream.  This is 
587
* mainly useful for debugging purposes.
588
*
589
* @param out the print stream, where the key/value pairs are written to
590
* @throws ClassCastException if this property contains a key or a
591
*         value that isn't a string
592
* @see #list(PrintWriter)
593
*/
594
public void list(PrintStream out)
595
{
596
 PrintWriter writer = new PrintWriter (out);
597
 list (writer);
598
}
599

  
600
/**
601
* Prints the key/value pairs to the given print writer.  This is
602
* mainly useful for debugging purposes.
603
*
604
* @param out the print writer where the key/value pairs are written to
605
* @throws ClassCastException if this property contains a key or a
606
*         value that isn't a string
607
* @see #list(PrintStream)
608
* @since 1.1
609
*/
610
public void list(PrintWriter out)
611
{
612
 out.println ("-- listing properties --");
613

  
614
 Iterator iter = entrySet ().iterator ();
615
 int i = size ();
616
 while (--i >= 0)
617
   {
618
     Entry entry = (Entry) iter.next ();
619
     out.print ((String) entry.getKey () + "=");
620

  
621
     // JDK 1.3/1.4 restrict the printed value, but not the key,
622
     // to 40 characters, including the truncating ellipsis.
623
     String s = (String ) entry.getValue ();
624
     if (s != null && s.length () > 40)
625
       out.println (s.substring (0, 37) + "...");
626
     else
627
       out.println (s);
628
   }
629
 out.flush ();
630
}
631

  
632
/**
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff