KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > serialization > SVGSerializer


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.serialization;
17
18 import java.awt.Color JavaDoc;
19 import java.io.OutputStream JavaDoc;
20 import java.io.Serializable JavaDoc;
21
22 import org.apache.avalon.excalibur.pool.Poolable;
23 import org.apache.avalon.framework.configuration.Configurable;
24 import org.apache.avalon.framework.configuration.Configuration;
25 import org.apache.avalon.framework.configuration.ConfigurationException;
26 import org.apache.avalon.framework.context.Context;
27 import org.apache.avalon.framework.context.ContextException;
28 import org.apache.avalon.framework.context.Contextualizable;
29 import org.apache.batik.transcoder.Transcoder;
30 import org.apache.batik.transcoder.TranscoderInput;
31 import org.apache.batik.transcoder.TranscoderOutput;
32 import org.apache.batik.transcoder.TranscodingHints;
33 import org.apache.batik.transcoder.TranscoderException;
34 import org.apache.batik.util.ParsedURL;
35 import org.apache.cocoon.Constants;
36 import org.apache.cocoon.caching.CacheableProcessingComponent;
37 import org.apache.cocoon.components.transcoder.ExtendableTranscoderFactory;
38 import org.apache.cocoon.components.transcoder.TranscoderFactory;
39 import org.apache.cocoon.components.url.ParsedContextURLProtocolHandler;
40 import org.apache.cocoon.components.url.ParsedResourceURLProtocolHandler;
41 import org.apache.cocoon.util.ClassUtils;
42 import org.apache.cocoon.xml.dom.SVGBuilder;
43 import org.apache.commons.lang.BooleanUtils;
44 import org.apache.excalibur.source.SourceValidity;
45 import org.apache.excalibur.source.impl.validity.NOPValidity;
46 import org.w3c.dom.Document JavaDoc;
47 import org.xml.sax.SAXException JavaDoc;
48
49 /**
50  * A <a HREF="http://xml.apache.org/batik/">Batik</a> based Serializer for generating PNG/JPEG images
51  *
52  * @author <a HREF="mailto:dims@yahoo.com">Davanum Srinivas</a>
53  * @author <a HREF="mailto:rossb@apache.org">Ross Burton</a>
54  * @version CVS $Id: SVGSerializer.java 123788 2004-12-31 12:43:00Z antonio $
55  */

56 public class SVGSerializer extends SVGBuilder
57 implements Serializer, Configurable, Poolable, CacheableProcessingComponent, Contextualizable {
58
59     /**
60      * Get the context
61      */

62     public void contextualize(Context context) throws ContextException {
63         ParsedContextURLProtocolHandler.setContext(
64             (org.apache.cocoon.environment.Context)context.get(Constants.CONTEXT_ENVIRONMENT_CONTEXT));
65         ParsedURL.registerHandler(new ParsedContextURLProtocolHandler());
66         ParsedURL.registerHandler(new ParsedResourceURLProtocolHandler());
67     }
68
69     /** The current <code>OutputStream</code>. */
70     private OutputStream JavaDoc output;
71
72     /** The current <code>mime-type</code>. */
73     private String JavaDoc mimetype;
74
75     /** The current <code>Transcoder</code>. */
76     Transcoder transcoder;
77
78     /** The Transcoder Factory to use */
79     TranscoderFactory factory = ExtendableTranscoderFactory.getTranscoderFactoryImplementation();
80     
81 // private ServiceManager manager;
82

83 // private SourceResolver resolver;
84

85     /**
86      * Set the <code>OutputStream</code> where the XML should be serialized.
87      */

88     public void setOutputStream(OutputStream JavaDoc out) {
89         this.output = out;
90         
91         // Give the source resolver to Batik
92
//SourceProtocolHandler.setup(this.resolver);
93
}
94     
95 /* public void service(ServiceManager manager) throws ServiceException {
96         this.manager = manager;
97         this.resolver = (SourceResolver)this.manager.lookup(SourceResolver.ROLE);
98     }
99
100     public void dispose() {
101         this.manager.release(this.resolver);
102     }
103 */

104     /**
105      * Set the configurations for this serializer.
106      */

107     public void configure(Configuration conf) throws ConfigurationException {
108         this.mimetype = conf.getAttribute("mime-type");
109         if (getLogger().isDebugEnabled()) {
110             getLogger().debug("mime-type: " + mimetype);
111         }
112
113         // Using the Transcoder Factory, get the default transcoder
114
// for this MIME type.
115
this.transcoder = factory.createTranscoder(mimetype);
116
117         // Iterate through the parameters, looking for a transcoder reference
118
Configuration[] parameters = conf.getChildren("parameter");
119         for (int i = 0; i < parameters.length; i++) {
120             String JavaDoc name = parameters[i].getAttribute("name");
121             if ("transcoder".equals(name)) {
122                 String JavaDoc transcoderName = parameters[i].getAttribute("value");
123                 try {
124                     this.transcoder = (Transcoder)ClassUtils.newInstance(transcoderName);
125                 } catch (Exception JavaDoc ex) {
126                     if (getLogger().isDebugEnabled()) {
127                         getLogger().debug("Cannot load class " + transcoderName, ex);
128                     }
129                     throw new ConfigurationException("Cannot load class " + transcoderName, ex);
130                 }
131             }
132         }
133         // Do we have a transcoder yet?
134
if (this.transcoder == null ) {
135             throw new ConfigurationException(
136                 "Could not autodetect transcoder for SVGSerializer and "
137                 + "no transcoder was specified in the sitemap configuration."
138             );
139         }
140
141         // Now run through the other parameters, using them as hints
142
// to the transcoder
143
for (int i = 0; i < parameters.length; i++ ) {
144             String JavaDoc name = parameters[i].getAttribute("name");
145             // Skip over the parameters we've dealt with. Ensure this
146
// is kept in sync with the above list!
147
if ("transcoder".equals(name)) {
148                 continue;
149             }
150
151             // Now try and get the hints out
152
try {
153                 // Turn it into a key name (assume the current Batik style continues!
154
name = ("KEY_" + name).toUpperCase();
155                 // Use reflection to get a reference to the key object
156
TranscodingHints.Key key = (TranscodingHints.Key)
157                     (transcoder.getClass().getField(name).get(transcoder));
158                 Object JavaDoc value;
159                 String JavaDoc keyType = parameters[i].getAttribute("type", "STRING").toUpperCase();
160                 if ("FLOAT".equals(keyType)) {
161                     // Can throw an exception.
162
value = new Float JavaDoc(parameters[i].getAttributeAsFloat("value"));
163                 } else if ("INTEGER".equals(keyType)) {
164                     // Can throw an exception.
165
value = new Integer JavaDoc(parameters[i].getAttributeAsInteger("value"));
166                 } else if ("BOOLEAN".equals(keyType)) {
167                     // Can throw an exception.
168
value = BooleanUtils.toBooleanObject(parameters[i].getAttributeAsBoolean("value"));
169                 } else if ("COLOR".equals(keyType)) {
170                     // Can throw an exception
171
String JavaDoc stringValue = parameters[i].getAttribute("value");
172                     if (stringValue.startsWith("#")) {
173                         stringValue = stringValue.substring(1);
174                     }
175                     value = new Color JavaDoc(Integer.parseInt(stringValue, 16));
176                 } else {
177                     // Assume String, and get the value. Allow an empty string.
178
value = parameters[i].getAttribute("value", "");
179                 }
180                 if(getLogger().isDebugEnabled()) {
181                     getLogger().debug("Adding hint \"" + name + "\" with value \"" + value.toString() + "\"");
182                 }
183                 transcoder.addTranscodingHint(key, value);
184             } catch (ClassCastException JavaDoc ex) {
185                 // This is only thrown from the String keyType... line
186
throw new ConfigurationException("Specified key (" + name + ") is not a valid Batik Transcoder key.", ex);
187             } catch (ConfigurationException ex) {
188                 throw new ConfigurationException("Name or value not specified.", ex);
189             } catch (IllegalAccessException JavaDoc ex) {
190                 throw new ConfigurationException("Cannot access the key for parameter \"" + name + "\"", ex);
191             } catch (NoSuchFieldException JavaDoc ex) {
192                 throw new ConfigurationException("No field available for parameter \"" + name + "\"", ex);
193             }
194         }
195     }
196
197     /**
198      * Receive notification of a successfully completed DOM tree generation.
199      */

200     public void notify(Document JavaDoc doc) throws SAXException JavaDoc {
201         
202         try {
203             TranscoderInput transInput = new TranscoderInput(doc);
204
205             // Buffering is done by the pipeline (See shouldSetContentLength)
206
TranscoderOutput transOutput = new TranscoderOutput(this.output);
207             transcoder.transcode(transInput, transOutput);
208         } catch (TranscoderException ex) {
209             if (ex.getException() != null) {
210                 if (getLogger().isDebugEnabled()) {
211                     getLogger().debug("Got transcoder exception writing image, rethrowing nested exception", ex);
212                 }
213                 throw new SAXException JavaDoc("Exception writing image", ex.getException());
214             }
215
216             if (getLogger().isDebugEnabled()) {
217                 getLogger().debug("Got transcoder exception writing image, rethrowing", ex);
218             }
219             throw new SAXException JavaDoc("Exception writing image", ex);
220         } catch (Exception JavaDoc ex) {
221             if (getLogger().isDebugEnabled()) {
222                 getLogger().debug("Got exception writing image, rethrowing", ex);
223             }
224             throw new SAXException JavaDoc("Exception writing image", ex);
225         }
226     }
227
228     /**
229      * Return the MIME type.
230      */

231     public String JavaDoc getMimeType() {
232         return mimetype;
233     }
234
235     /**
236      * Generate the unique key.
237      * This key must be unique inside the space of this component.
238      * This method must be invoked before the getValidity() method.
239      *
240      * @return The generated key or <code>0</code> if the component
241      * is currently not cacheable.
242      */

243     public Serializable JavaDoc getKey() {
244         return "1";
245     }
246
247     /**
248      * Generate the validity object.
249      * Before this method can be invoked the getKey() method
250      * must be invoked.
251      *
252      * @return The generated validity object or <code>null</code> if the
253      * component is currently not cacheable.
254      */

255     public SourceValidity getValidity() {
256         return NOPValidity.SHARED_INSTANCE;
257     }
258
259     /**
260      * Returns true so the pipeline implementation will buffer generated
261      * output and write content length to the response.
262      * <p>Batik's PNGTranscoder closes the output stream, therefore we
263      * cannot pass the output stream directly to Batik and have to
264      * instruct pipeline to buffer it. If we do not buffer, we would get
265      * an exception when
266      * {@link org.apache.cocoon.Cocoon#process(org.apache.cocoon.environment.Environment)}
267      * tries to close the stream.
268      */

269     public boolean shouldSetContentLength() {
270         return true;
271     }
272 }
273
Popular Tags