View Javadoc

1   /*
2    * All Rights Reserved.
3    * Copyright (C) 1999-2005 Tsukuba Bunko.
4    *
5    * Licensed under the BSD License ("the License"); you may not use
6    * this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    *
9    *       http://www.tsukuba-bunko.org/licenses/LICENSE.txt
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   *
17   * $Id: ResourceLoader.java,v 1.2 2005/07/24 20:55:57 ppoi Exp $
18   */
19  package tsukuba_bunko.resource;
20  
21  import	java.io.IOException;
22  
23  import	java.net.URL;
24  
25  import	java.util.Iterator;
26  import	java.util.List;
27  
28  import	javax.xml.parsers.ParserConfigurationException;
29  import	javax.xml.parsers.SAXParserFactory;
30  
31  import	org.xml.sax.Attributes;
32  import	org.xml.sax.ContentHandler;
33  import	org.xml.sax.Locator;
34  import	org.xml.sax.SAXException;
35  import	org.xml.sax.XMLReader;
36  
37  
38  /***
39   * リソースファイルを読み込む機能を提供します.
40   * この実装では,マルチスレッドはサポートされません.
41   * @author	$Author: ppoi $
42   * @version	$Revision: 1.2 $
43   */
44  public class ResourceLoader implements ContentHandler	{
45  
46  	/***
47  	 * パースに使用する XMLReader
48  	 */
49  	private XMLReader	_parser = null;
50  
51  	/***
52  	 * DeserializerMapping
53  	 */
54  	private DeserializerMapping	_mapping = DeserializerMapping.newInstance();
55  
56  	/***
57  	 * 現在使用中の ResourceDeserializer
58  	 */
59  	private ResourceDeserializer	_currentDeserializer = null;
60  
61  	/***
62  	 * レベル
63  	 */
64  	private int	_level = 0;
65  
66  	/***
67  	 * パススタック
68  	 */
69  	private List	_stack = null;
70  
71  	/***
72  	 * テキストバッファ
73  	 */
74  	private StringBuffer	_text = null;
75  
76  
77  	/***
78  	 * リソースを管理する Resources
79  	 */
80  	private Resources	_resources = null;
81  
82  
83  	/***
84  	 * <code>ResourceLoader</code> のインスタンスを作成します.
85  	 * @exception	ParserConfigurationException	JAXP が正しく構成されていない場合
86  	 * @exception	SAXException	JAXP が正しく構成されていない場合
87  	 */
88  	public ResourceLoader()
89  		throws ParserConfigurationException, SAXException
90  	{
91  		super();
92  
93  		SAXParserFactory	factory = SAXParserFactory.newInstance();
94  		factory.setNamespaceAware( true );
95  		_parser = factory.newSAXParser().getXMLReader();
96  		_parser.setContentHandler( this );
97  	}
98  
99  
100 	/***
101 	 * リソースの解析に使用する <code>DeserializerMapping</code> を設定します.
102 	 * @param	mapping	リソースの解析に使用する <code>DeserializerMapping</code>
103 	 */
104 	public void setDeserializerMapping( DeserializerMapping mapping )
105 	{
106 		_mapping = mapping;
107 	}
108 
109 	/***
110 	 * リソースの解析に使用する <code>DeserializerMapping</code> を取得します.
111 	 * @return	リソースの解析に使用する <code>DeserializerMapping</code>
112 	 */
113 	public DeserializerMapping getDeserializerMapping()
114 	{
115 		return _mapping;
116 	}
117 
118 	/***
119 	 * リソースを読み込みます.
120 	 * @param	resourceURL	リソースファイルの URL
121 	 * @param	resources	リソースを登録する <code>Resources</code> オブジェクト
122 	 */
123 	public void loadResource( URL resourceURL, Resources resources )
124 		throws IOException, IllegalResourceException
125 	{
126 		try	{
127 			_resources = resources;
128 			_parser.parse( resourceURL.toString() );
129 			_resources = null;
130 		}
131 		catch( SAXException se )	{
132 			throw new IllegalResourceException( se );
133 		}
134 	}
135 
136 	/***
137 	 * ResourceDeserializer を取得します。
138 	 * @param	namespaceURI	XML namespace URI
139 	 * @param	localName	tag name (local part)
140 	 * @param	qName	tag name (quorified name)
141 	 * @param	attrs	attributes
142 	 * @throws	SAXException	不正なデータ型を検出した場合
143 	 */
144 	protected ResourceDeserializer getResourceDeserializer( String namespaceURI, String localName, String qName, Attributes attrs )
145 		throws SAXException
146 	{
147 		if( _mapping == null )	{
148 			return null;
149 		}
150 
151 		String	dataType = attrs.getValue( "type" );
152 		if( dataType != null )	{
153 			ResourceDeserializer	deserializer = _mapping.getResourceDeserializer( dataType );
154 			if( deserializer == null )	{
155 				throw new SAXException( "no deserializer for \"" + dataType + "\"" );
156 			}
157 			return deserializer;
158 		}
159 		else	{
160 			return null;
161 		}
162 	}
163 
164 	/***
165 	 * 現在のパスを計算します.
166 	 * @return	パス
167 	 */
168 	protected String getCurrentPath()
169 	{
170 		StringBuffer	buffer = new StringBuffer();
171 		Iterator	itr = _stack.iterator();
172 		if( itr.hasNext() )	{
173 			itr.next();
174 		}
175 
176 		if( itr.hasNext() )	{
177 			buffer.append( itr.next() );
178 		}
179 		while( itr.hasNext() )	{
180 			buffer.append( "." );
181 			buffer.append( itr.next() );
182 		}
183 		return new String(buffer);
184 	}
185 
186 
187 //
188 //	ContentHandler の実装
189 //
190 	public void setDocumentLocator( Locator locator )
191 	{
192 	}
193 
194 	public void startPrefixMapping( String namespaceURI, String prefix )
195 		throws SAXException
196 	{
197 		if( _currentDeserializer != null )	{
198 			_currentDeserializer.startPrefixMapping( namespaceURI, prefix );
199 		}
200 	}
201 
202 	public void endPrefixMapping( String namespaceURI )
203 		throws SAXException
204 	{
205 		if( _currentDeserializer != null )	{
206 			_currentDeserializer.endPrefixMapping( namespaceURI );
207 		}
208 	}
209 
210 	public void startDocument()
211 	{
212 		_stack = new java.util.ArrayList();
213 		if( _mapping == null )	{
214 			_mapping = DeserializerMapping.newInstance();
215 		}
216 	}
217 
218 	public void endDocument()
219 	{
220 		_stack = null;
221 	}
222 
223 	public void startElement( String namespaceURI, String localName, String qName, Attributes attrs )
224 		throws SAXException
225 	{
226 		if( _currentDeserializer != null )	{
227 			_level++;
228 			_currentDeserializer.startElement( namespaceURI, localName, qName, attrs );
229 		}
230 		else	{
231 			_stack.add( qName );
232 
233 			ResourceDeserializer	deserializer = getResourceDeserializer( namespaceURI, localName, qName, attrs );
234 			if( deserializer != null )	{
235 				_currentDeserializer = deserializer;
236 				deserializer.setDeserializerMapping( _mapping );
237 				_level++;
238 				deserializer.startDocument();
239 				deserializer.startElement( namespaceURI, localName, qName, attrs );
240 			}
241 			else	{
242 				_text = new StringBuffer();
243 			}
244 		}
245 	}
246 
247 	public void endElement( String namespaceURI, String localName, String qName )
248 		throws SAXException
249 	{
250 		if( _currentDeserializer != null )	{
251 			_level--;
252 			_currentDeserializer.endElement( namespaceURI, localName, qName );
253 			if( _level == 0 )	{
254 				_currentDeserializer.endDocument();
255 				_resources.setResource( getCurrentPath(), _currentDeserializer.getValue() );
256 				_stack.remove( _stack.size() - 1 );
257 				_currentDeserializer = null;
258 				_currentDeserializer = null;
259 			}
260 		}
261 		else if( _text != null )	{
262 			_resources.setResource( getCurrentPath(), new String(_text) );
263 			_stack.remove( _stack.size() - 1 );
264 		}
265 		else	{
266 			_stack.remove( _stack.size() - 1 );
267 		}
268 		_text = null;
269 	}
270 
271 	public void processingInstruction( String target, String data )
272 		throws SAXException
273 	{
274 		if( _currentDeserializer != null )	{
275 			_currentDeserializer.processingInstruction( target, data );
276 		}
277 	}
278 
279 	public void skippedEntity( String name )
280 		throws SAXException
281 	{
282 		if( _currentDeserializer != null )	{
283 			_currentDeserializer.skippedEntity( name );
284 		}
285 	}
286 
287 	public void characters( char[] ch, int begin, int length )
288 		throws SAXException
289 	{
290 		if( _currentDeserializer != null )	{
291 			_currentDeserializer.characters( ch, begin, length );
292 		}
293 		else if( _text != null )	{
294 			_text.append( ch, begin, length );
295 		}
296 	}
297 
298 	public void ignorableWhitespace( char[] ch, int begin, int length )
299 		throws SAXException
300 	{
301 		if( _currentDeserializer != null )	{
302 			_currentDeserializer.ignorableWhitespace( ch, begin, length );
303 		}
304 	}
305 }