Hi, Here's proposed SVGSerializer patch to support request parameters.
The following changes have been made: Configuration ============= 1. The <use-request-parametes> tag is recognized to allow the serializer to use request parameters. if true ==> All the declared batik keys can be overriden by request parameters. 3. The value attribute of the key now means it's a default value and is not mandatory anymore. 4. A default TranscodingHints is configured with all the keys entries which have a default value 5. A Map is used to keep information on batik transcoding keys and their "types" (INTEGER, ...) Processing ========== 1. The SVGSerializer implements the SitemapModelComponent 2. A current TranscodingHints is built overriding the default one and adding new key values if their "types" can be resolved. EXEMPLE ======= 1. in the batik block sitemap add this instead of the current the svg2png serializer: <map:serializer logger="sitemap.serializer.svg2png" name="svg2png" src="org.apache.cocoon.serialization.SVGSerializer" mime-type="image/png"> <use-request-parameters>true</use-request-parameters> <parameter name="indexed" type="integer" value="16"/> <parameter name="height" type="float"/> <parameter name="width" type="float"/> </map:serializer> 2. Try this: samples/batik/batikLogo.png ... the normal logo or samples/batik/batikLogo.png?width=200&height=100 ... small logo or samples/batik/batikLogo.png?width=200&height=100&indexed=2 ... ugly! ===== BORGES C. ___________________________________________________________ Do You Yahoo!? -- Une adresse @yahoo.fr gratuite et en français ! Yahoo! Mail : http://fr.mail.yahoo.com
Index: SVGSerializer.java =================================================================== RCS file: /home/cvspublic/cocoon-2.1/src/blocks/batik/java/org/apache/cocoon/serialization/SVGSerializer.java,v retrieving revision 1.9 diff -u -r1.9 SVGSerializer.java --- SVGSerializer.java 9 Oct 2003 15:26:54 -0000 1.9 +++ SVGSerializer.java 19 Nov 2003 17:44:26 -0000 @@ -51,7 +51,12 @@ package org.apache.cocoon.serialization; import java.awt.Color; +import java.io.IOException; import java.io.OutputStream; +import java.io.Serializable; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; import org.apache.avalon.excalibur.pool.Poolable; import org.apache.avalon.framework.component.ComponentManager; @@ -62,6 +67,7 @@ import org.apache.avalon.framework.context.Context; import org.apache.avalon.framework.context.ContextException; import org.apache.avalon.framework.context.Contextualizable; +import org.apache.avalon.framework.parameters.Parameters; import org.apache.batik.transcoder.Transcoder; import org.apache.batik.transcoder.TranscoderInput; import org.apache.batik.transcoder.TranscoderOutput; @@ -69,11 +75,16 @@ import org.apache.batik.transcoder.TranscoderException; import org.apache.batik.util.ParsedURL; import org.apache.cocoon.Constants; +import org.apache.cocoon.ProcessingException; import org.apache.cocoon.caching.CacheableProcessingComponent; import org.apache.cocoon.components.transcoder.ExtendableTranscoderFactory; import org.apache.cocoon.components.transcoder.TranscoderFactory; import org.apache.cocoon.components.url.ParsedContextURLProtocolHandler; import org.apache.cocoon.components.url.ParsedResourceURLProtocolHandler; +import org.apache.cocoon.environment.ObjectModelHelper; +import org.apache.cocoon.environment.Request; +import org.apache.cocoon.environment.SourceResolver; +import org.apache.cocoon.sitemap.SitemapModelComponent; import org.apache.cocoon.util.ClassUtils; import org.apache.cocoon.xml.dom.SVGBuilder; import org.apache.excalibur.source.SourceValidity; @@ -89,7 +100,7 @@ * @version CVS $Id: SVGSerializer.java,v 1.9 2003/10/09 15:26:54 sylvain Exp $ */ public class SVGSerializer extends SVGBuilder -implements Composable, Serializer, Configurable, Poolable, CacheableProcessingComponent, Contextualizable { +implements Composable, Serializer, Configurable, Poolable, CacheableProcessingComponent, Contextualizable, SitemapModelComponent { /** * Get the context @@ -112,7 +123,22 @@ /** The Transcoder Factory to use */ TranscoderFactory factory = ExtendableTranscoderFactory.getTranscoderFactoryImplementation(); - + + /** The current caching key */ + private Serializable cachingKey; + + /** The default Batik <code>TranscodingHints</code> set up in configuration step */ + private TranscodingHints defaultTranscodingHints; + + /** The current Batik <code>TranscodingHints</code> can overrides the default one */ + private TranscodingHints currentTranscodingHints; + + /** The map holding information for the Batik <code>TranscodingHints.Key</code>s */ + private Map transcodingHintKeysInfo; + + /** Override default <code>TranscodingHints</code> with request parameters? */ + private boolean overrideTranscodingHints = false; + //private boolean _overrideTranscodingHints = false; /** * Set the <code>OutputStream</code> where the XML should be serialized. */ @@ -157,8 +183,10 @@ ); } - // Now run through the other parameters, using them as hints - // to the transcoder + // Now run through the other parameters, adding them to the + // default transcoding hints + defaultTranscodingHints = new TranscodingHints(); + transcodingHintKeysInfo = new HashMap(); for (int i = 0; i < parameters.length; i++ ) { String name = parameters[i].getAttribute("name"); // Skip over the parameters we've dealt with. Ensure this @@ -169,48 +197,94 @@ // Now try and get the hints out try { - // Turn it into a key name (assume the current Batik style continues! - name = ("KEY_" + name).toUpperCase(); - // Use reflection to get a reference to the key object - TranscodingHints.Key key = (TranscodingHints.Key) - (transcoder.getClass().getField(name).get(transcoder)); - Object value; - String keyType = parameters[i].getAttribute("type", "STRING").toUpperCase(); - if ("FLOAT".equals(keyType)) { - // Can throw an exception. - value = new Float(parameters[i].getAttributeAsFloat("value")); - } else if ("INTEGER".equals(keyType)) { - // Can throw an exception. - value = new Integer(parameters[i].getAttributeAsInteger("value")); - } else if ("BOOLEAN".equals(keyType)) { - // Can throw an exception. - value = new Boolean(parameters[i].getAttributeAsBoolean("value")); - } else if ("COLOR".equals(keyType)) { - // Can throw an exception - String stringValue = parameters[i].getAttribute("value"); - if (stringValue.startsWith("#")) { - stringValue = stringValue.substring(1); + String batikKeyName = "KEY_" + name.toUpperCase(); + String batikKeyType = parameters[i].getAttribute("type", "STRING").toUpperCase(); + //Use reflection to get a reference to the key object + TranscodingHints.Key key = (TranscodingHints.Key) (this.transcoder.getClass().getField(batikKeyName).get(this.transcoder)); + + //The value is not required. It can only declares a default value for a key + Object value = computeBatikKeyValue(batikKeyType, parameters[i].getAttribute("value", null)); + + // Adding transcoding hint value + if (value != null) { + if(getLogger().isDebugEnabled()) { + getLogger().debug("Adding default hint \"" + name + "\" with value \"" + value.toString() + "\""); } - value = new Color(Integer.parseInt(stringValue, 16)); - } else { - // Assume String, and get the value. Allow an empty string. - value = parameters[i].getAttribute("value", ""); - } - if(getLogger().isDebugEnabled()) { - getLogger().debug("Adding hint \"" + name + "\" with value \"" + value.toString() + "\""); + defaultTranscodingHints.put(key, value); } - transcoder.addTranscodingHint(key, value); + + // Adding info for all declared keys + TranscodingHintKeyInfo keyInfo = new TranscodingHintKeyInfo(batikKeyName, batikKeyType, key); + transcodingHintKeysInfo.put(name, keyInfo); + } catch (ClassCastException ex) { // This is only thrown from the String keyType... line throw new ConfigurationException("Specified key (" + name + ") is not a valid Batik Transcoder key.", ex); - } catch (ConfigurationException ex) { - throw new ConfigurationException("Name or value not specified.", ex); } catch (IllegalAccessException ex) { throw new ConfigurationException("Cannot access the key for parameter \"" + name + "\"", ex); } catch (NoSuchFieldException ex) { throw new ConfigurationException("No field available for parameter \"" + name + "\"", ex); } } + + // Setting default value to enable overriding default transcoding hints + overrideTranscodingHints = + conf.getChild("use-request-parameters").getValueAsBoolean(false); + if (getLogger().isDebugEnabled() && overrideTranscodingHints) { + getLogger().debug( + "The transcoding hints may be overrinden by request parameters"); + } + } + + /** + * Set the <code>SourceResolver</code>, the <code>Map</code> with + * the object model, the source and sitemap + * <code>Parameters</code> used to process the request. + */ + public void setup(SourceResolver resolver, Map objectModel, String src, Parameters par) throws ProcessingException, SAXException, IOException { + currentTranscodingHints = (TranscodingHints) defaultTranscodingHints.clone(); + cachingKey = "1"; + // Overrides configured batik tranciding hints values with request parameters? + //this._overrideTranscodingHints = par.getParameterAsBoolean("use-request-parameters", overrideTranscodingHints); + if (this.overrideTranscodingHints) { + Request request = ObjectModelHelper.getRequest(objectModel); + Enumeration parameters = request.getParameterNames(); + if (parameters != null) { + StringBuffer cachingKeyBuffer = new StringBuffer(); + while (parameters.hasMoreElements()) { + String parameterName = (String) parameters.nextElement(); + if (transcodingHintKeysInfo + .containsKey(parameterName)) { + TranscodingHintKeyInfo keyInfo = (TranscodingHintKeyInfo) transcodingHintKeysInfo.get(parameterName); + String batikKeyName = keyInfo.getName(); + String batikKeyType = keyInfo.getType(); + TranscodingHints.Key batikKey = keyInfo.getTranscodingHintKey(); + String value = request.getParameter(parameterName); + Object batikKeyValue = + computeBatikKeyValue(batikKeyType, value); + if (batikKeyValue == null) { + getLogger().info("Cannot compute value for parameter " + parameterName + " (" +batikKeyName + "). If a default value was set, it will be used instead."); + } else { + if (getLogger().isDebugEnabled()) { + getLogger().debug("Setting " + parameterName + " (" + batikKeyName + ") value to " + batikKeyValue.toString()); + } + currentTranscodingHints.put(batikKey, batikKeyValue); + cachingKeyBuffer.append(";"); + cachingKeyBuffer.append(parameterName); + cachingKeyBuffer.append("="); + cachingKeyBuffer.append(value); + } + + } + } + String currentCachingKey = cachingKeyBuffer.toString().trim(); + if (currentCachingKey.length() > 0) { + cachingKey = currentCachingKey; + } + } + + } + } /** @@ -229,6 +303,8 @@ // Buffering is done by the pipeline (See shouldSetContentLength) TranscoderOutput transOutput = new TranscoderOutput(this.output); + // Setting current transcoding hints to transcoder + transcoder.setTranscodingHints(currentTranscodingHints); transcoder.transcode(transInput, transOutput); } catch (TranscoderException ex) { if (ex.getException() != null) { @@ -265,8 +341,8 @@ * @return The generated key or <code>0</code> if the component * is currently not cacheable. */ - public java.io.Serializable getKey() { - return "1"; + public Serializable getKey() { + return cachingKey; } /** @@ -293,4 +369,119 @@ public boolean shouldSetContentLength() { return true; } + + /** + * Computes the transcoding hint value for a key type declared in + * the configuration of this serializer. + * + * @param keyType The key type. + * @param value The string value to be converted into an object. + * @return The object value. it will return null if the value + * cannot be computed or the key type is unknown. + */ + private Object computeBatikKeyValue(String type, String value) { + if (value == null) { + return null; + } + if ("STRING".equals(type)) { + return value; + } + if (value.length() == 0) { + return null; + } + if ("FLOAT".equals(type)) { + try { + return Float.valueOf(value); + } catch (NumberFormatException e) { + return null; + } + } + if ("INTEGER".equals(type)) { + + try { + return Integer.valueOf(value); + } catch (NumberFormatException e) { + return null; + } + + } + if ("BOOLEAN".equals(type)) { + return Boolean.valueOf(value); + } + if ("COLOR".equals(type)) { + // Can throw an exception + if (value.startsWith("#")) { + value = value.substring(1); + } + try { + return new Color(Integer.parseInt(value, 16)); + } catch (NumberFormatException e) { + return null; + } + } + return null; + } + + /** + * This is a convinience class to hold information on the configured + * Batik keys + */ + private static final class TranscodingHintKeyInfo { + + /** key type as of INTEGER, ... */ + private String type; + + /** batik key name starting with KEY_ */ + private String name; + + /** batik <code>TranscodingHints.Key</code> */ + private TranscodingHints.Key key; + + /** + * Constructor + * + * @param name The batik key name + * @param type The configured key type + * @param batikKey The <code>TranscodingHints.Key</code> + */ + public TranscodingHintKeyInfo( + String name, + String type, + TranscodingHints.Key batikKey){ + this.name = name; + this.type = type; + this.key = batikKey; + + } + + /** + * Gets the batik key name + * + * @return The batik key name + */ + public String getName() { + return name; + } + + /** + * Gets the configured key type + * + * @return The key type + */ + public String getType() { + return type; + } + + /** + * Gets the <code>TranscodingHints.Key</code> + * + * @return The <code>TranscodingHints.Key</code> + */ + public TranscodingHints.Key getTranscodingHintKey() { + return key; + } + + } + + }
SVGSerializer.java
Description: SVGSerializer.java