1
+ package org .threeten .bp .chrono
2
+
3
+ import java .io .IOException
4
+ import java .io .File
5
+ import java .io .FileInputStream
6
+ import java .io .BufferedReader
7
+ import java .io .DataInput
8
+ import java .io .DataOutput
9
+ import java .io .IOException
10
+ import java .io .InputStream
11
+ import java .io .InputStreamReader
12
+ import java .io .Serializable
13
+ import java .util .zip .ZipEntry
14
+ import java .util .zip .ZipFile
15
+ import java .util .{Objects , StringTokenizer }
16
+ import java .text .ParseException
17
+
18
+ object HijrahDateConfigurator {
19
+ /** File separator. */
20
+ private val FILE_SEP : Char = File .separatorChar
21
+ /** Path separator. */
22
+ private val PATH_SEP : String = File .pathSeparator
23
+ /** Default config file name. */
24
+ private val DEFAULT_CONFIG_FILENAME : String = " hijrah_deviation.cfg"
25
+ /** Default path to the config file. */
26
+ private val DEFAULT_CONFIG_PATH : String = s " org ${FILE_SEP }threeten ${FILE_SEP }bp ${FILE_SEP }chrono "
27
+
28
+
29
+ /** Read hijrah_deviation.cfg file. The config file contains the deviation data with
30
+ * following format.
31
+ *
32
+ * StartYear/StartMonth(0-based)-EndYear/EndMonth(0-based):Deviation day (1,
33
+ * 2, -1, or -2)
34
+ *
35
+ * Line separator or ";" is used for the separator of each deviation data.
36
+ *
37
+ * Here is the example.
38
+ *
39
+ * 1429/0-1429/1:1
40
+ * 1429/2-1429/7:1;1429/6-1429/11:1
41
+ * 1429/11-9999/11:1
42
+ *
43
+ * @throws IOException for zip/jar file handling exception.
44
+ * @throws ParseException if the format of the configuration file is wrong.
45
+ */
46
+ @ throws[IOException ]
47
+ @ throws[ParseException ]
48
+ private [chrono] def readDeviationConfig (): Unit = {
49
+ val is : InputStream = getConfigFileInputStream
50
+ if (is != null ) {
51
+ var br : BufferedReader = null
52
+ try {
53
+ br = new BufferedReader (new InputStreamReader (is))
54
+ var line : String = " "
55
+ var num : Int = 0
56
+ while ({line = br.readLine; line} != null ) {
57
+ num += 1
58
+ line = line.trim
59
+ parseLine(line, num)
60
+ }
61
+ } finally {
62
+ if (br != null )
63
+ br.close()
64
+ }
65
+ }
66
+ }
67
+
68
+ /** Parse each deviation element.
69
+ *
70
+ * @param line a line to parse
71
+ * @param num line number
72
+ * @throws ParseException if line has incorrect format.
73
+ */
74
+ @ throws[ParseException ]
75
+ private def parseLine (line : String , num : Int ): Unit = {
76
+ val st : StringTokenizer = new StringTokenizer (line, " ;" )
77
+ while (st.hasMoreTokens) {
78
+ val deviationElement : String = st.nextToken
79
+ val offsetIndex : Int = deviationElement.indexOf(':' )
80
+ if (offsetIndex != - 1 ) {
81
+ val offsetString : String = deviationElement.substring(offsetIndex + 1 , deviationElement.length)
82
+ var offset : Int = 0
83
+ try offset = offsetString.toInt
84
+ catch {
85
+ case ex : NumberFormatException =>
86
+ throw new ParseException (s " Offset is not properly set at line $num. " , num)
87
+ }
88
+ val separatorIndex : Int = deviationElement.indexOf('-' )
89
+ if (separatorIndex != - 1 ) {
90
+ val startDateStg : String = deviationElement.substring(0 , separatorIndex)
91
+ val endDateStg : String = deviationElement.substring(separatorIndex + 1 , offsetIndex)
92
+ val startDateYearSepIndex : Int = startDateStg.indexOf('/' )
93
+ val endDateYearSepIndex : Int = endDateStg.indexOf('/' )
94
+ var startYear : Int = - 1
95
+ var endYear : Int = - 1
96
+ var startMonth : Int = - 1
97
+ var endMonth : Int = - 1
98
+ if (startDateYearSepIndex != - 1 ) {
99
+ val startYearStg : String = startDateStg.substring(0 , startDateYearSepIndex)
100
+ val startMonthStg : String = startDateStg.substring(startDateYearSepIndex + 1 , startDateStg.length)
101
+ try startYear = startYearStg.toInt
102
+ catch {
103
+ case ex : NumberFormatException =>
104
+ throw new ParseException (s " Start year is not properly set at line $num. " , num)
105
+ }
106
+ try startMonth = startMonthStg.toInt
107
+ catch {
108
+ case ex : NumberFormatException =>
109
+ throw new ParseException (s " Start month is not properly set at line $num. " , num)
110
+ }
111
+ }
112
+ else
113
+ throw new ParseException (s " Start year/month has incorrect format at line $num. " , num)
114
+ if (endDateYearSepIndex != - 1 ) {
115
+ val endYearStg : String = endDateStg.substring(0 , endDateYearSepIndex)
116
+ val endMonthStg : String = endDateStg.substring(endDateYearSepIndex + 1 , endDateStg.length)
117
+ try endYear = endYearStg.toInt
118
+ catch {
119
+ case ex : NumberFormatException =>
120
+ throw new ParseException (s " End year is not properly set at line $num. " , num)
121
+ }
122
+ try {
123
+ endMonth = endMonthStg.toInt
124
+ }
125
+ catch {
126
+ case ex : NumberFormatException =>
127
+ throw new ParseException (s " End month is not properly set at line $num. " , num)
128
+ }
129
+ }
130
+ else
131
+ throw new ParseException (s " End year/month has incorrect format at line $num. " , num)
132
+ if (startYear != - 1 && startMonth != - 1 && endYear != - 1 && endMonth != - 1 )
133
+ HijrahDate .addDeviationAsHijrah(startYear, startMonth, endYear, endMonth, offset)
134
+ else
135
+ throw new ParseException (s " Unknown error at line $num. " , num)
136
+ }
137
+ else
138
+ throw new ParseException (s " Start and end year/month has incorrect format at line $num. " , num)
139
+ }
140
+ else
141
+ throw new ParseException (s " Offset has incorrect format at line $num. " , num)
142
+ }
143
+ }
144
+
145
+ /** Return InputStream for deviation configuration file.
146
+ * The default location of the deviation file is:
147
+ * <pre>
148
+ * $CLASSPATH/org/threeten/bp/chrono
149
+ * </pre>
150
+ * And the default file name is:
151
+ * <pre>
152
+ * hijrah_deviation.cfg
153
+ * </pre>
154
+ * The default location and file name can be overriden by setting
155
+ * following two Java's system property.
156
+ * <pre>
157
+ * Location: org.threeten.bp.i18n.HijrahDate.deviationConfigDir
158
+ * File name: org.threeten.bp.i18n.HijrahDate.deviationConfigFile
159
+ * </pre>
160
+ * Regarding the file format, see readDeviationConfig() method for details.
161
+ *
162
+ * @return InputStream for file reading exception.
163
+ * @throws IOException for zip/jar file handling exception.
164
+ */
165
+ @ throws[IOException ]
166
+ private def getConfigFileInputStream : InputStream = {
167
+ var fileName : String = System .getProperty(" org.threeten.bp.i18n.HijrahDate.deviationConfigFile" )
168
+ if (fileName == null )
169
+ fileName = DEFAULT_CONFIG_FILENAME
170
+ var dir : String = System .getProperty(" org.threeten.bp.i18n.HijrahDate.deviationConfigDir" )
171
+ if (dir != null ) {
172
+ if (! (dir.length == 0 && dir.endsWith(System .getProperty(" file.separator" ))))
173
+ dir = dir + System .getProperty(" file.separator" )
174
+ val file : File = new File (dir + FILE_SEP + fileName)
175
+ if (file.exists) {
176
+ try new FileInputStream (file)
177
+ catch {
178
+ case ioe : IOException =>
179
+ throw ioe
180
+ }
181
+ }
182
+ else null
183
+ }
184
+ else {
185
+ val classPath : String = System .getProperty(" java.class.path" )
186
+ val st : StringTokenizer = new StringTokenizer (classPath, PATH_SEP )
187
+ while (st.hasMoreTokens) {
188
+ val path : String = st.nextToken
189
+ val file : File = new File (path)
190
+ if (file.exists) {
191
+ if (file.isDirectory) {
192
+ val f : File = new File (path + FILE_SEP + DEFAULT_CONFIG_PATH , fileName)
193
+ if (f.exists) {
194
+ try return new FileInputStream (path + FILE_SEP + DEFAULT_CONFIG_PATH + FILE_SEP + fileName)
195
+ catch {
196
+ case ioe : IOException => throw ioe
197
+ }
198
+ }
199
+ }
200
+ else {
201
+ var zip : ZipFile = null
202
+ try zip = new ZipFile (file)
203
+ catch {
204
+ case ioe : IOException => zip = null
205
+ }
206
+ if (zip != null ) {
207
+ var targetFile : String = DEFAULT_CONFIG_PATH + FILE_SEP + fileName
208
+ var entry : ZipEntry = zip.getEntry(targetFile)
209
+ if (entry == null ) {
210
+ if (FILE_SEP == '/' )
211
+ targetFile = targetFile.replace('/' , '\\ ' )
212
+ else if (FILE_SEP == '\\ ' )
213
+ targetFile = targetFile.replace('\\ ' , '/' )
214
+ entry = zip.getEntry(targetFile)
215
+ }
216
+ if (entry != null ) {
217
+ try return zip.getInputStream(entry)
218
+ catch {
219
+ case ioe : IOException => throw ioe
220
+ }
221
+ }
222
+ }
223
+ }
224
+ }
225
+ }
226
+ null
227
+ }
228
+ }
229
+ }
0 commit comments