1 /*------------------------------------------------------------------------------
  2 Name:      PluginConfigSaxFactory.java
  3 Project:   xmlBlaster.org
  4 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
  5 ------------------------------------------------------------------------------*/
  6 package org.xmlBlaster.util;
  7 
  8 import java.util.logging.Level;
  9 import java.util.logging.Logger;
 10 
 11 import org.xml.sax.Attributes;
 12 import org.xmlBlaster.util.def.ErrorCode;
 13 
 14 
 15 /**
 16  * This class parses an xml string to generate an Attribute which can be used either in PluginConfig or on the 
 17  * normal properties server- or clientside.
 18  * <p>
 19  * @author <a href="mailto:michele@laghi.eu">Michele Laghi</a>
 20  * @author <a href="mailto:xmlBlaster@marcelruff.info">Marcel Ruff</a>
 21  * @see <a href="http://www.xmlblaster.org/xmlBlaster/doc/requirements/engine.runlevel.html">engine.runlevel requirement</a>
 22  * <pre>
 23  *  &lt;action do='LOAD'
 24  *             onStartupRunlevel='3'
 25  *             sequence='5'
 26  *             onFail='RESOURCE_CONFIGURATION_PLUGINFAILED'/>
 27  * </pre>
 28  */
 29 public class AttributeSaxFactory extends SaxHandlerBase
 30 {
 31    private String ME = "AttributeSaxFactory";
 32    private final Global glob;
 33    private static Logger log = Logger.getLogger(AttributeSaxFactory.class.getName());
 34 
 35    private XmlBlasterException ex;
 36 
 37    private I_AttributeUser attributeUser;
 38    private String attributeKey;
 39    private boolean attributeReplace; // replace ${xy} tokens? defaults to true since xmlBlaster v2.2 2012-01-09 
 40    private StringBuffer attributeValue;
 41    private boolean inAttribute = false;
 42    private boolean wrappedInCDATA = false; // for example: <attribute id='publishQos'><![CDATA[ bla ]]></attribute>
 43    private boolean embeddedCDATA = false;  // for example: <attribute id='publishQos'><qos><![CDATA[<expiration lifeTime='4000'/>]]></qos></attribute>
 44    private int subTagCounter;
 45 
 46    /**
 47     * Can be used as singleton. 
 48     */
 49    public AttributeSaxFactory(Global glob, I_AttributeUser attributeUser) {
 50       super(glob);
 51       setUseLexicalHandler(true); // to allow CDATA wrapped attributes 
 52       this.glob = glob;
 53       this.attributeUser = attributeUser;
 54    }
 55 
 56    /**
 57     * resets the factory (to be invoked before parsing)
 58     */
 59    public void reset(I_AttributeUser attributeUser) {
 60       this.attributeUser = attributeUser;
 61       this.ex = null; // reset the exeptions
 62       this.wrappedInCDATA = false;
 63    }
 64 
 65    public boolean isInAttribute() {
 66       return this.inAttribute;
 67    }
 68    
 69    /**
 70     * Start element, event from SAX parser.
 71     * <p />
 72     * @param name Tag name
 73     * @param attrs the attributes of the tag
 74     */
 75    public final void startElement(String uri, String localName, String name, Attributes attrs) {
 76       if (this.ex != null ) return;
 77 
 78       if ("attribute".equalsIgnoreCase(name)) {
 79          this.inAttribute = true;
 80          this.wrappedInCDATA = false;
 81          this.attributeKey = attrs.getValue("id");
 82          this.attributeReplace = true;
 83          String replace = attrs.getValue("replace");
 84          if (replace != null && "false".equalsIgnoreCase(replace))
 85           this.attributeReplace = false;
 86          this.attributeValue = new StringBuffer(1024);
 87          if (this.attributeKey == null || this.attributeKey.length() < 1)
 88             this.ex = new XmlBlasterException(this.glob, ErrorCode.RESOURCE_CONFIGURATION, ME + ".startElement",  "the attributes in the <plugin> tag must have an non-empty 'id' attribute");
 89          return;
 90       }
 91 
 92       if (this.inAttribute) {
 93          this.subTagCounter++;
 94          this.attributeValue.append("<").append(name);
 95          for (int i=0; i<attrs.getLength(); i++) {
 96             String qName = attrs.getQName(i);
 97             String val = attrs.getValue(i);
 98             this.attributeValue.append(" ").append(qName).append("='").append(val).append("'");
 99          }
100          this.attributeValue.append(">");
101       }
102       else {
103          log.warning("startElement: unknown tag '" + name + "'");
104       }
105    }
106 
107    public void startCDATA() {
108       if (log.isLoggable(Level.FINER)) log.finer("startCDATA");
109       this.wrappedInCDATA = true;
110       if (this.subTagCounter > 0) {
111          this.attributeValue.append("<![CDATA[");
112          this.embeddedCDATA = true;
113       }
114    }
115 
116    /**
117     * The characters to be filled
118     */
119    public void characters(char[] ch, int start, int length) {
120       if (this.attributeValue != null)
121          this.attributeValue.append(ch, start, length);
122    }
123 
124 
125    /**
126     * End element, event from SAX parser.
127     * <p />
128     * @param name Tag name
129     */
130    public void endElement(String uri, String localName, String name) {
131       if (this.ex != null ) return;
132       if ("attribute".equalsIgnoreCase(name)) {
133          this.inAttribute = false;
134          this.subTagCounter = 0;
135          if (this.attributeKey != null && this.attributeValue != null) {
136             String val = this.attributeValue.toString();
137 
138             /*if (val.startsWith("<![CDATA[")) {*/  //if (this.wrappedInCDATA) {
139             if (false) { // currently bypassed since we don't want to strip &lt;![CDATA[ 
140                // Strip CDATA if ampersand '&lt;![CDATA[' was used instead of '<![CDATA[':
141                int pos = val.indexOf("<![CDATA[");
142                if (pos >= 0) {
143                   val = val.substring(pos+9);
144                }
145                pos = val.lastIndexOf("]]>");
146                if (pos >= 0) {
147                   val = val.substring(0, pos);
148                }
149             }
150             if (this.attributeUser != null) {
151                this.attributeUser.addAttribute(this.attributeKey, val, this.attributeReplace);
152                if (this.wrappedInCDATA) {
153                   this.attributeUser.wrapAttributeInCDATA(this.attributeKey);
154                   this.wrappedInCDATA = false;
155                }
156             }
157          }
158          this.attributeKey = null;
159          this.attributeValue = null;
160          return;
161       }   
162       if (this.inAttribute) {
163          if (this.embeddedCDATA) {
164             this.attributeValue.append("]]>");
165             this.embeddedCDATA = false;
166          }
167          this.attributeValue.append("</"+name+">");
168          this.subTagCounter--;
169       }
170    }
171 
172    /**
173     * A human readable name of this factory
174     * @return "AttributeSaxFactory"
175     */
176    public String getName() {
177       return "AttributeSaxFactory";
178    }
179 }


syntax highlighted by Code2HTML, v. 0.9.1