001: /* Copyright 2002 The JA-SIG Collaborative. All rights reserved.
002: * See license distributed with this file and
003: * available online at http://www.uportal.org/license.html
004: */
005:
006: package org.jasig.portal.car;
007:
008: import org.apache.commons.logging.Log;
009: import org.apache.commons.logging.LogFactory;
010: import org.jasig.portal.tools.versioning.Version;
011: import org.jasig.portal.tools.versioning.VersionsManager;
012: import org.xml.sax.Attributes;
013: import org.xml.sax.SAXException;
014: import org.xml.sax.helpers.DefaultHandler;
015:
016: /**
017: * Handles a "processIf" tag looking for the following attributes and
018: * blocking SAX events from reaching nested tags if the specified
019: * requirements are not met.
020: *
021: * <pre>
022: * fname = the functional name whose version is to be checked
023: * version = value is one of lessThan, greaterThan, lessThanOrEqual,
024: * greaterThanOrEqual, equalTo, or notEqualTo.
025: * major = the revision level major part
026: * minor = the revision level minor part
027: * micro = the revision level micro part
028: * setMajor = optional, the new revision level major part
029: * setMinor = optional, the new revision level minor part
030: * setMicro = optional, the new revision level micro part
031: * </pre>
032: *
033: * The contents of the processIf tag are only processed if the version
034: * of the specified fname matches the requirements as specified in the
035: * version, major, minor, and micro attributes. If the setMajor,
036: * setMinor, and setMicro attributes are specified then and additional
037: * test is performed to determine if processing will occur. This test
038: * involves attempting to set the version of the fname to that
039: * specified. If unable to then processing will be skipped for this
040: * block. This is done to allow the same CAR to be deployed on all
041: * servers in a multi-server deployment but only have on of the
042: * servers perform the processing of the block and affect the
043: * database.
044: *
045: * There is no limit on the number of processIf blocks that can occur
046: * in a deployment descriptor. All other nested tags are supported
047: * within the processIf tag. The processIf tag can not be nested
048: * inside of itself.
049: *
050: *
051: * @author Mark Boyd {@link <a href="mailto:mark.boyd@engineer.com">mark.boyd@engineer.com</a>}
052: * @version $Revision: 36690 $
053: */
054: public class ProcessIfTagHandler extends DefaultHandler {
055: private static final Log log = LogFactory
056: .getLog(ProcessIfTagHandler.class);
057: private boolean enabled = false;
058: private RoutingHandler routingHandler = null;
059: private ParsingContext ctx = null;
060:
061: private static final String LESS_THAN = "lessThan";
062: private static final String GTR_THAN = "greaterThan";
063: private static final String LESS_THAN_OR_EQU = "lessThanOrEqual";
064: private static final String GTR_THAN_OR_EQU = "greaterThanOrEqual";
065: private static final String EQU = "equalTo";
066: private static final String NOT_EQU = "notEqualTo";
067:
068: ProcessIfTagHandler(ParsingContext ctx,
069: RoutingHandler routingHandler) {
070: this .routingHandler = routingHandler;
071: this .ctx = ctx;
072: }
073:
074: /**
075: * Passes the attributes of the processIf tag that is currently
076: * being parsed to this handler allowing it to determine if it
077: * should allow SAX events to be passed to the contained tag
078: * handlers or not.
079: *
080: * @param atts
081: **/
082: void setAttributes(Attributes atts) {
083: // determine if process tag is enabled or not
084: enabled = false;
085:
086: // aquire and validate major, minor, & micro
087: int major = -1;
088: int minor = -1;
089: int micro = -1;
090: int setMajor = -1;
091: int setMinor = -1;
092: int setMicro = -1;
093: String setDescription = null;
094:
095: try {
096: major = Integer.parseInt(atts.getValue("major"));
097: minor = Integer.parseInt(atts.getValue("minor"));
098: micro = Integer.parseInt(atts.getValue("micro"));
099: if (major < 0 || minor < 0 || micro < 0)
100: throw new IllegalArgumentException();
101: } catch (Exception e) {
102: log.error("The deployment descriptor "
103: + CarResources.DEPLOYMENT_DESCRIPTOR + " in "
104: + ctx.getJarFile().getName()
105: + " contains an invalid "
106: + DescriptorHandler.PROCESS_TAG_NAME
107: + " tag. It must contain major, minor, and micro, "
108: + " and each must have zero or a positive"
109: + " integer value. Ignoring contents of block.");
110: return;
111: }
112:
113: setDescription = atts.getValue("setDescription");
114:
115: boolean newVersionIncluded = atts.getValue("setMajor") != null
116: || atts.getValue("setMinor") != null
117: || atts.getValue("setMicro") != null
118: || setDescription != null;
119:
120: try {
121: if (newVersionIncluded) {
122: setMajor = Integer.parseInt(atts.getValue("setMajor"));
123: setMinor = Integer.parseInt(atts.getValue("setMinor"));
124: setMicro = Integer.parseInt(atts.getValue("setMicro"));
125: if (setMajor < 0 || setMinor < 0 || setMicro < 0
126: || setDescription == null)
127: throw new IllegalArgumentException();
128: }
129: } catch (Exception e) {
130: log
131: .error("The deployment descriptor "
132: + CarResources.DEPLOYMENT_DESCRIPTOR
133: + " in "
134: + ctx.getJarFile().getName()
135: + " contains an invalid "
136: + DescriptorHandler.PROCESS_TAG_NAME
137: + " tag. If it contains setMajor, setMinor, setMicro,"
138: + " or setDescription attributes it must contain all four"
139: + " and each of the first three must have zero or a"
140: + " positive integer value. Ignoring contents of block.");
141: return;
142: }
143: // now aquire and validate ifVersion
144: String testType = atts.getValue("version");
145:
146: if (testType == null)
147: testType = EQU;
148:
149: if (!testType.equals(EQU) && !testType.equals(LESS_THAN)
150: && !testType.equals(LESS_THAN_OR_EQU)
151: && !testType.equals(GTR_THAN)
152: && !testType.equals(GTR_THAN_OR_EQU)
153: && !testType.equals(NOT_EQU)) {
154: log.error("The deployment descriptor "
155: + CarResources.DEPLOYMENT_DESCRIPTOR + " in "
156: + ctx.getJarFile().getName()
157: + " contains an invalid "
158: + DescriptorHandler.PROCESS_TAG_NAME
159: + " tag. If it contains an 'version' attribute the"
160: + " value of that attribute must be one of '" + EQU
161: + "', '" + NOT_EQU + "', '" + GTR_THAN + "', '"
162: + GTR_THAN_OR_EQU + "', '" + LESS_THAN + "', or '"
163: + LESS_THAN_OR_EQU
164: + "'. Ignoring contents of block.");
165: return;
166: }
167:
168: // now aquire and validate fname
169: String fname = atts.getValue("fname");
170: if (fname == null || fname.equals("")) {
171: log
172: .error("The deployment descriptor "
173: + CarResources.DEPLOYMENT_DESCRIPTOR
174: + " in "
175: + ctx.getJarFile().getName()
176: + " contains an invalid "
177: + DescriptorHandler.PROCESS_TAG_NAME
178: + " tag. It must contain a non-empty 'fname' attribute"
179: + " holding the functional name whose version is being"
180: + " tested. Ignoring contents of block.");
181: return;
182: }
183: // now see if version test indicates that the block should be processed
184: enabled = evaluate(testType, fname, major, minor, micro);
185:
186: // now see if we can set it to the new version if specified
187: if (enabled && newVersionIncluded) {
188: VersionsManager vMgr = VersionsManager.getInstance();
189: enabled = vMgr.setVersion(fname, setDescription, setMajor,
190: setMinor, setMicro);
191: }
192: }
193:
194: /**
195: * Determines if the version specified and the version recorded in the
196: * system indicate that the block should be processed.
197: *
198: * @param testType
199: * @param fname
200: * @param major
201: * @param minor
202: * @param micro
203: * @return true if the block should be processed.
204: */
205: private boolean evaluate(String testType, String fname, int major,
206: int minor, int micro) {
207: VersionsManager vMgr = VersionsManager.getInstance();
208: Version currVer = vMgr.getVersion(fname);
209: Version testVer = new Version(fname, "", major, minor, micro);
210:
211: if (currVer == null)
212: return true;
213:
214: if (testType.equals(EQU))
215: return currVer.equalTo(testVer);
216: else if (testType.equals(NOT_EQU))
217: return !currVer.equalTo(testVer);
218: else if (testType.equals(GTR_THAN))
219: return currVer.greaterThan(testVer);
220: else if (testType.equals(GTR_THAN_OR_EQU))
221: return currVer.greaterThan(testVer)
222: || currVer.equalTo(testVer);
223: else if (testType.equals(LESS_THAN))
224: return currVer.lessThan(testVer);
225: else if (testType.equals(LESS_THAN_OR_EQU))
226: return currVer.lessThan(testVer)
227: || currVer.equalTo(testVer);
228:
229: // should never get here
230: return false;
231: }
232:
233: /////// ContentHandler methods of interest
234:
235: public void startElement(java.lang.String namespaceURI,
236: java.lang.String localName, java.lang.String qName,
237: Attributes atts) throws SAXException {
238: if (enabled)
239: routingHandler.startElement(namespaceURI, localName, qName,
240: atts);
241: }
242:
243: public void endElement(java.lang.String namespaceURI,
244: java.lang.String localName, java.lang.String qName)
245: throws SAXException {
246: if (enabled)
247: routingHandler.endElement(namespaceURI, localName, qName);
248: }
249:
250: public void characters(char[] ch, int start, int length)
251: throws SAXException {
252: if (enabled)
253: routingHandler.characters(ch, start, length);
254: }
255: }
|