/*
* Copyright (c) 2004-2005 Ant-Contrib project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.sf.antcontrib.design;
import java.io.File;
import java.util.Stack;
import org.apache.tools.ant.Location;
import org.apache.tools.ant.Project;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
/**
* Handler for the root element. Its only child must be the "project" element.
*/
class DesignFileHandler implements ContentHandler {
private final static String DESIGN = "design";
private final static String PACKAGE = "package";
private final static String DEPENDS = "depends";
private Log log = null;
private File file = null;
private boolean isCircularDesign;
private boolean needDeclarationsDefault = true;
private boolean needDependsDefault = true;
private Design design = null;
private Package currentPackage = null;
private Stack stack = new Stack();
private Locator locator = null;
private Location loc;
/**
* @param CompileWithWalls
*/
DesignFileHandler(Log log, File file, boolean isCircularDesign, Location loc) {
this.log = log;
this.file = file;
this.isCircularDesign = isCircularDesign;
this.loc = loc;
}
/**
* @param needDeclarationsDefault
*/
public void setNeedDeclarationsDefault(boolean b) {
needDeclarationsDefault = b;
}
/**
* @param needDependsDefault
*/
public void setNeedDependsDefault(boolean b) {
needDependsDefault = b;
}
public Design getDesign() {
return design;
}
/**
* Resolves file: URIs relative to the build file.
*
* @param publicId The public identifer, or null
* if none is available. Ignored in this
* implementation.
* @param systemId The system identifier provided in the XML
* document. Will not be null
.
*/
public InputSource resolveEntity(String publicId,
String systemId) {
log.log("publicId="+publicId+" systemId="+systemId,
Project.MSG_VERBOSE);
return null;
}
/**
* Sets the locator in the project helper for future reference.
*
* @param locator The locator used by the parser.
* Will not be null
.
*/
public void setDocumentLocator(Locator locator) {
this.locator = locator;
}
/**
* @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String, java.lang.String)
*/
public void startPrefixMapping(String prefix, String uri) throws SAXException {
}
/**
* @see org.xml.sax.ContentHandler#endPrefixMapping(java.lang.String)
*/
public void endPrefixMapping(String prefix) throws SAXException {
}
/**
* @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
*/
public void startElement(String uri, String name, String qName, Attributes attrs) throws SAXException {
log.log("Parsing startElement="+name, Project.MSG_DEBUG);
if (name == null || "".equals(name)) {
// XMLReader is not-namespace aware
name = qName;
}
try {
Object o = null;
if(name.equals(DESIGN)) {
o = handleDesign(attrs);
} else if(name.equals(PACKAGE)) {
currentPackage = handlePackage(attrs);
o = currentPackage;
} else if(name.equals(DEPENDS)) {
o = handleDepends(attrs);
} else {
throw new SAXParseException("Error in file="+file.getAbsolutePath()
+", Unexpected element \"" + name + "\"", locator);
}
stack.push(o);
} catch(RuntimeException e) {
log.log("exception111111111111111111", Project.MSG_INFO);
throw new SAXParseException("PRoblem parsing", locator, e);
}
}
private Design handleDesign(Attributes attrs) throws SAXParseException {
if(attrs.getLength() > 0)
throw new SAXParseException("Error in file="+file.getAbsolutePath()
+", no attributes allowed for "+DESIGN+" element", locator);
else if(stack.size() > 0)
throw new SAXParseException("Error in file="+file.getAbsolutePath()
+", "+DESIGN+" cannot be a subelement of "+stack.pop(), locator);
else if(attrs.getLength() > 0)
throw new SAXParseException("Error in file="+file.getAbsolutePath()
+", "+DESIGN+" element can't have any attributes", locator);
design = new Design(isCircularDesign, log, loc);
return design;
}
private Package handlePackage(Attributes attrs) throws SAXParseException {
if(stack.size() <= 0 || !(stack.peek() instanceof Design))
throw new SAXParseException("Error in file="+file.getAbsolutePath()
+", "+PACKAGE+" element must be nested in a "+DESIGN+" element", locator);
int len = attrs.getLength();
String name = null;
String thePackage = null;
String depends = null;
String subpackages = null;
String needDeclarations = null;
String needDepends = null;
for(int i = 0; i < len; i++) {
String attrName = attrs.getLocalName(i);
if ("".equals(attrName)) {
// XMLReader is not-namespace aware
attrName = attrs.getQName(i);
}
String value = attrs.getValue(i);
log.log("attr="+attrName+" value="+value, Project.MSG_DEBUG);
if("name".equals(attrName))
name = value;
else if("package".equals(attrName))
thePackage = value;
else if("depends".equals(attrName))
depends = value;
else if("subpackages".equals(attrName))
subpackages = value;
else if("needdeclarations".equals(attrName))
needDeclarations = value;
else if("needdepends".equals(attrName))
needDepends = value;
else
throw new SAXParseException("Error in file="+file.getAbsolutePath()
+"\n'"+attrName+"' attribute is an invalid attribute for the package element", locator);
}
//set the defaults
if(subpackages == null)
subpackages = "exclude";
if(needDeclarations == null)
needDeclarations = Boolean.toString(needDeclarationsDefault);
if(needDepends == null)
needDepends = Boolean.toString(needDependsDefault);
//make sure every attribute had a valid value...
if(name == null)
throw new SAXParseException("Error in file="+file.getAbsolutePath()
+", package element must contain the 'name' attribute", locator);
else if(thePackage == null)
throw new SAXParseException("Error in file="+file.getAbsolutePath()
+", package element must contain the 'package' attribute", locator);
else if(!("include".equals(subpackages) || "exclude".equals(subpackages)))
throw new SAXParseException("Error in file="+file.getAbsolutePath()
+"\nThe subpackages attribute in the package element can only have a"
+"\nvalue of \"include\" or \"exclude\". value='"+subpackages+"'", locator);
else if(!("true".equals(needDeclarations) || "false".equals(needDeclarations)))
throw new SAXParseException("Error in file="+file.getAbsolutePath()
+"\nThe needdeclarations attribute in the package element can only have a"
+"\nvalue of \"true\" or \"false\". value='"+needDeclarations+"'", locator);
else if(!("true".equals(needDepends) || "false".equals(needDepends)))
throw new SAXParseException("Error in file="+file.getAbsolutePath()
+"\nThe needdepends attribute in the package element can only have a"
+"\nvalue of \"true\" or \"false\". value='"+needDepends+"'", locator);
Package p = new Package();
p.setName(name);
p.setPackage(thePackage);
if("exclude".equals(subpackages))
p.setIncludeSubpackages(false);
else
p.setIncludeSubpackages(true);
if("true".equals(needDeclarations))
p.setNeedDeclarations(true);
else
p.setNeedDeclarations(false);
if("true".equals(needDepends))
p.setNeedDepends(true);
else
p.setNeedDepends(false);
if(depends != null)
p.addDepends(new Depends(depends));
return p;
}
private Depends handleDepends(Attributes attrs) throws SAXParseException {
if(stack.size() <= 0 || !(stack.peek() instanceof Package))
throw new SAXParseException("Error in file="+file.getAbsolutePath()
+", "+DEPENDS+" element must be nested in a "+PACKAGE+" element", locator);
else if(attrs.getLength() > 0)
throw new SAXParseException("Error in file="+file.getAbsolutePath()
+", "+DEPENDS+" element can't have any attributes", locator);
return new Depends();
}
/**
* @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
*/
public void endElement(String uri, String localName, String qName) throws SAXException {
try {
Object o = stack.pop();
if(o instanceof Package) {
Package p = (Package)o;
Package tmp = design.getPackage(p.getName());
if(tmp != null)
throw new SAXParseException("Error in file="+file.getAbsolutePath()
+"\nname attribute on "+PACKAGE+" element has the same\n"
+"name as another package. name=\""+p.getName()+"\" is used twice or more", locator);
design.addConfiguredPackage(p);
currentPackage = null;
} else if(o instanceof Depends) {
Depends d = (Depends)o;
currentPackage.addDepends(d);
}
} catch(RuntimeException e) {
throw new SAXParseException("exception", locator, e);
}
}
/**
* @see org.xml.sax.ContentHandler#skippedEntity(java.lang.String)
*/
public void skippedEntity(String name) throws SAXException {
}
/**
* @see org.xml.sax.ContentHandler#startDocument()
*/
public void startDocument() throws SAXException {
}
/**
* @see org.xml.sax.ContentHandler#endDocument()
*/
public void endDocument() throws SAXException {
}
/**
* @see org.xml.sax.ContentHandler#characters(char[], int, int)
*/
public void characters(char[] ch, int start, int length) throws SAXException {
try {
Object o = stack.peek();
if(o instanceof Depends) {
String s = new String(ch, start, length);
Depends d = (Depends)o;
if (d.getName() != null)
d.setName(d.getName() + s.trim());
else
d.setName(s.trim());
}
} catch(RuntimeException e) {
log.log("exception3333333333333333333", Project.MSG_INFO);
throw new SAXParseException("exception", locator, e);
}
}
/**
* @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int)
*/
public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
}
/**
* @see org.xml.sax.ContentHandler#processingInstruction(java.lang.String, java.lang.String)
*/
public void processingInstruction(String target, String data) throws SAXException {
}
}