KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > components > serializers > encoding > CharsetFactory


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.cocoon.components.serializers.encoding;
17
18 import java.io.ByteArrayOutputStream JavaDoc;
19 import java.io.File JavaDoc;
20 import java.io.PrintWriter JavaDoc;
21 import java.io.PrintStream JavaDoc;
22 import java.io.IOException JavaDoc;
23 import java.io.OutputStreamWriter JavaDoc;
24 import java.io.UnsupportedEncodingException JavaDoc;
25 import java.net.URL JavaDoc;
26 import java.util.Enumeration JavaDoc;
27 import java.util.HashMap JavaDoc;
28 import java.util.zip.ZipEntry JavaDoc;
29 import java.util.zip.ZipFile JavaDoc;
30
31 /**
32  *
33  *
34  * @author <a HREF="mailto:pier@apache.org">Pier Fumagalli</a>, February 2003
35  * @version CVS $Id: CharsetFactory.java 54667 2004-10-12 12:21:45Z tcurdt $
36  */

37 public final class CharsetFactory {
38
39     /** The lookup class name for the encodings. */
40     private static final String JavaDoc CHARSET_LOOKUP_CLASS =
41         "org/apache/cocoon/components/serializers/encoding/cs_US_ASCII.class";
42
43     /** Our private instance. */
44     private static CharsetFactory instance = new CharsetFactory();
45
46     /** The instance of the JVM default <code>Charset</code>. */
47     private Charset defaultCharset = null;
48
49     /** The instance of the JVM unknown <code>Charset</code>. */
50     private Charset unknownCharset = null;
51
52     /** All our charsets, mapped by their name and aliases. */
53     private HashMap JavaDoc charsets = new HashMap JavaDoc();
54
55     /**
56      * Create a new instance of this <code>CharsetFactory</code>.
57      */

58     private CharsetFactory() {
59         super();
60         this.unknownCharset = new UnknownCharset();
61
62         ClassLoader JavaDoc loader = Thread.currentThread().getContextClassLoader();
63         URL JavaDoc url = loader.getResource(CHARSET_LOOKUP_CLASS);
64
65         if (url == null) {
66             throw new CharsetFactoryException("Unable to load charsets "
67                     + "because their classes are not present", null);
68         }
69
70         if ("jar".equals(url.getProtocol())) {
71             this.loadCharsetsFromJar(url);
72         } else if ("file".equals(url.getProtocol())) {
73             this.loadCharsetsFromFile(url);
74         } else {
75             throw new CharsetFactoryException("Unable to load charsets " +
76                         "from protocol \"" + url.getProtocol() + "\"", null);
77         }
78
79         ByteArrayOutputStream JavaDoc otmp = new ByteArrayOutputStream JavaDoc();
80         OutputStreamWriter JavaDoc wtmp = new OutputStreamWriter JavaDoc(otmp);
81         String JavaDoc etmp = wtmp.getEncoding();
82         try {
83             defaultCharset = this.getCharset(etmp);
84         } catch (UnsupportedEncodingException JavaDoc exception) {
85             throw new CharsetFactoryException("The default encoding of this "
86                 + "JVM \"" + etmp + "\" is not supported", exception);
87         }
88
89     }
90
91     /**
92      * Load a <code>Charset</code> into this factory.
93      */

94     private void loadCharset(Charset charset) {
95         this.charsets.put(charset.getName().toLowerCase(), charset);
96         String JavaDoc aliases[] = charset.getAliases();
97         for (int x = 0; x < aliases.length; x++) {
98             this.charsets.put(aliases[x].toLowerCase(), charset);
99         }
100     }
101
102     /**
103      * Instantiate and load a <code>Charset</code> into this factory.
104      */

105     private void loadCharset(String JavaDoc clazz) {
106         try {
107             Class JavaDoc c = Class.forName(clazz);
108             Object JavaDoc o = c.newInstance();
109             if (o instanceof Charset) {
110                 loadCharset((Charset)o);
111             }
112         } catch (Exception JavaDoc exception) {
113             throw new CharsetFactoryException("Unable to instantiate class \""
114                                               + clazz + "\"", exception);
115         }
116     }
117
118     /**
119      * Load all <code>Charset</code> available if this class was loaded
120      * from a JAR file.
121      */

122     private void loadCharsetsFromJar(URL JavaDoc url) {
123         try {
124             String JavaDoc file = url.getFile();
125             String JavaDoc mtch = file.substring(file.indexOf('!'));
126             file = file.substring(5, file.indexOf('!'));
127             mtch = mtch.substring(2, mtch.lastIndexOf('/') + 1) + "cs_";
128     
129             ZipFile JavaDoc zip = new ZipFile JavaDoc(file);
130             Enumeration JavaDoc enumeration = zip.entries();
131             while (enumeration.hasMoreElements()) {
132                 ZipEntry JavaDoc entry = (ZipEntry JavaDoc)enumeration.nextElement();
133                 String JavaDoc name = entry.getName();
134                 if ((! name.startsWith(mtch)) ||
135                     (! name.endsWith(".class"))) continue;
136                 name = name.substring(mtch.length());
137                 name = ".cs_" + name.substring(0, name.length() - 6);
138                 name = this.getClass().getPackage().getName() + name;
139                 loadCharset(name);
140             }
141         } catch (IOException JavaDoc exception) {
142             throw new CharsetFactoryException("Unable to access JAR \""
143                                           + url.toString() + "\"", exception);
144         }
145     }
146
147     /**
148      * Load all <code>Charset</code> available if this class was loaded
149      * from a plain file on disk.
150      */

151     private void loadCharsetsFromFile(URL JavaDoc url) {
152         File JavaDoc file = new File JavaDoc(url.getFile()).getParentFile();
153         String JavaDoc children[] = file.list();
154         for (int x = 0; x < children.length; x++) {
155             String JavaDoc child = children[x];
156             if ((! child.startsWith("cs_")) ||
157                 (! child.endsWith(".class"))) continue;
158             child = '.' + child.substring(0, child.length() - 6);
159             child = this.getClass().getPackage().getName() + child;
160             this.loadCharset(child);
161         }
162     }
163
164     /**
165      * Return an instance of this <code>CharsetFactory</code>.
166      */

167     public static CharsetFactory newInstance() {
168         if (instance != null) return (instance);
169         synchronized (CharsetFactory.class) {
170             if (instance != null) return (instance);
171             instance = new CharsetFactory();
172         }
173         return(instance);
174     }
175
176     /**
177      * Return the <code>Charset</code> instance for the unknown charset.
178      * <br />
179      * All calls to the <code>allows(...)</code> method of the returned
180      * <code>Charset</code> will return <b>true</b>.
181      */

182     public Charset getCharset() {
183         return(unknownCharset);
184     }
185
186     /**
187      * Return the <code>Charset</code> instance for the default charset.
188      *
189      */

190     public Charset getDefaultCharset() {
191         return(defaultCharset);
192     }
193
194     /**
195      * Return the <code>Charset</code> instance for a specifc charset.
196      *
197      * @throws UnsupportedEncodingException If the specified is invalid or
198      * cannot be accessed.
199      */

200     public Charset getCharset(String JavaDoc name)
201     throws UnsupportedEncodingException JavaDoc {
202         if (name == null) return(this.getDefaultCharset());
203         Charset charset = (Charset)this.charsets.get(name.toLowerCase());
204         if (charset != null) return(charset);
205         throw new UnsupportedEncodingException JavaDoc("Unsupported charset \""
206                                                + name + "\"");
207     }
208
209     /**
210      * An <code>RuntimeException</code> thrown if something bad happens
211      * while initializing our factory.
212      */

213     private static class CharsetFactoryException extends RuntimeException JavaDoc {
214
215         /** The root cause of this exception. */
216         private Exception JavaDoc exception = null;
217
218         /**
219          * Create a new <code>CharsetFactoryException</code> instance.
220          */

221         private CharsetFactoryException(String JavaDoc message, Exception JavaDoc exception) {
222             super(message == null? exception.getMessage(): message);
223             this.exception = exception;
224         }
225
226         /**
227          * Return the <code>Exception</code> cause of this exception.
228          */

229         public Exception JavaDoc getException() {
230             return(this.exception);
231         }
232
233         /**
234          * Print this <code>Exception</code> stacktrace to a specified
235          * <code>PrintWriter</code>.
236          */

237         public void printStackTrace(PrintWriter JavaDoc out) {
238             super.printStackTrace(out);
239             if (this.exception != null) {
240                 out.print("Root cause: ");
241                 this.exception.printStackTrace(out);
242             }
243         }
244
245         /**
246          * Print this <code>Exception</code> stacktrace to a specified
247          * <code>PrintStream</code>.
248          */

249         public void printStackTrace(PrintStream JavaDoc out) {
250             super.printStackTrace(out);
251             if (this.exception != null) {
252                 out.print("Root cause: ");
253                 this.exception.printStackTrace(out);
254             }
255         }
256     }
257 }
258
Popular Tags