Wednesday, August 19, 2009

Exploring xsd.core

I mentioned in the previous blog that the getProperty() method under the class XSDSchemaAdapter in org.eclipse.wst.xsd.core, XSDImpl.java calculates the name space of an attribute. However, as i looked more into the code, I found that the getProperty() method does not do more than retrieving the value from a created attribute. So, to find out how the name space of an attribute is calculated, I would need to look into the code where an attribute is created.

First, I go back to org.eclipse.wst.xml.core, DOMContentBuilderImpl.java and find out the method creating an element, which is visitCMElementDeclaration(). In visitCMElementDeclaration(), the following line of code is trying to creat the attributes of an element.

CMNamedNodeMap nodeMap = ed.getAttributes();

When ed is passed to visitCMElementDeclaration(), it is claimed to be an instance of CMElementDeclaration, but it is actually of data type XSDElementDeclarationAdapter derived from ElementDeclarationBaseImpl. XSDElementDeclarationAdapter and ElementDeclarationBaseImpl are both defined in org.eclipse.wst.xsd.core, XSDImpl.java.getAttributes() is one of the methods defined in ElementDeclarationBaseImpl. The following lines of code in getAttributes() are creating the attributes of an element.

XSDComplexTypeDefinition ctd = (XSDComplexTypeDefinition) xsdTypeDefinition;
for (Iterator i = ctd.getAttributeUses().iterator(); i.hasNext();) {    XSDAttributeUse xsdAttributeUse = (XSDAttributeUse) i.next();
    XSDAttributeUseAdapter adapter =          (XSDAttributeUseAdapter)getAdapter(xsdAttributeUse);
    if (adapter != null && adapter.getNodeName() != null) {
       map.getHashtable().put(adapter.getNodeName(), adapter);
    }
}

The most important variable in the these lines is ctd, which is corresponding to the definition of an element. XSDComplexTypeDefinition is defined in org.eclipse.xsd_2.5.0.v200905041408.jar in the plug-in dependencies folder. At this point, the "lang" attribute still gets the correct name space url, which is http://www.w3c.org/XML/1998/namespace. However, once the CMNode, representing the "lang" attribute, is converted to CMDocument later in DOMNamespaceHelper.java, the namespace url, for some unknown reason, has been changed to http://java.sun.com/xml/ns/javaee, which I think is the cause of Bug 245698

Tuesday, August 18, 2009

Move from xml.core to xsd.core

In the past few weeks, I have looked into org.eclipse.wst.xsd.core, and find the following line of code in DOMNamespaceHelper.java calculating the name space of an element/attribute.

String qualification = (String)cmNode.getProperty("http://org.eclipse.wst/cm/properties/nsPrefixQualification");

The computerName() method from which I got the above line of code is called from the following line of code in DOMContentBuilderImpl.java, visitCMAttributeDeclaration().

String value = valueHelper.getValue(ad, namespaceTable);

ad is an instance of CMAttributeDeclaration, but it is really with the data type of XSDAttrubuteUseAdapter defined in org.eclipse.wst.xsd.core, XSDImpl.java. However, as it is shown in the line of code calculating the name space of an element/attribute, any CMNode object(in this case it is ad) is converted to a CMDocument first before the getProperty() method is invoked in DOMNamespaceHelper.java, computeName().

As a result of that, the getProperty() method invoked is the one under XSDSchemaAdapter class in XSDImpl.java, and the following lines of code are calculating the name space of element/attribute by calling getTargetNamespace().

if(propertyName.equals(PROPERTY_TARGET_NAMESPACE_URI)){
     result = xsdSchema.getTargetNamespace();
}

xsdSchema is an instance of org.eclipse.xsd.XSDSchema, which is defined in org.eclipse.xsd_2.5.0.v200905041408.jar in the plug-in dependencies folder.

Monday, August 3, 2009

More Code Inspection for Bug 245698

As I have mentioned I the previous post, the variable, contentBuilder which is an instance of DOMContentBuilderImpl, is handler the work of creating an XML document in createXMLDocument method of NewXMLGenetator.java. Specifically, the following line in createXMLDocument is trying to create an XML document:

contentBuilder.createDefaultRootContent(cmDocument, cmElementDeclaration, namespaceInfoList);

To get more detail about createDefaultRootContent, I checked out the code for DOMContentBuilderImpl.java, which is under org.eclipse.wst.xml.core >> src-contentmodel >> org.eclipse.wst.xml.core.internal.contentmodel.util.

When I looked into createDefaultRootContent in DOMContentBuilderImpl.java, I found out createDefaultRootContent is only creating the root element of an XML document, the method that actually create the other elements in an XML file is createDefaultContent. There are only three lines of code in createDefaultContent. The line dealing with creating XML document elements is:

visitCMElementDeclaration(ed);

So then, I looked into the function with the following signature in DOMContentBuilderImpl.java

public void visitCMElementDeclaration(CMElementDeclaration ed)

Within visitCMElementDeclaration, I found the following lines responsible for creating attributes within an element.

for (int j = 0; j < size; j++) {
visitCMNode(nodeMap.item(j));
}

DOMContentBuilderImpl.java does not have any definition for visitCMNode(), but DOMContentBuilderImpl extends from CMVisitor. So, I checked out the code for CMVisitor.java, which is in the same package as DOMContentBuilderImpl.java, and I found the definition for visitCMNode(). When I looked into the code for visitCMNode() in CMVisitor.java, I found that this method is doing more than creating attributes for an XML element, but when it is used to create attributes for an element, another method, visitCMAttributeDeclaration(), is called from visitCMNode(). In CMVisitor.java, I found that visitCMAttributeDeclaration() is declared, but not defined. So, I had to go back to DOMContentBuilderImpl.java to find out the definition for visitCMAttributeDeclaration(). Then I found the following line in visitCMAttributeDeclaration().

String name = computeName(ad, currentParent);

In this line of code, computeName() is the method used to calculated the qualified name of an attribute. So then, I move to the definition for computeName() in DOMContentBuilderImpl.java. There, computeName() in DOMNamespaceHelper is called to calculate the prefix of an attribute. Within computeName(), the following line is used to get the prefix of an attribute.

String qualification = (String)cmNode.getProperty("http://org.eclipse.wst/cm/properties/nsPrefixQualification");

In my old post "Cause of Bug245698", I have explained that the reason why the XML validator detects the error in the newly created XML document is the attribute has an wrong prefix. So to fix this bug, I have to look into the above line calculating the prefix of an attribute and figure out how the prefix is calculated.

Saturday, July 11, 2009

Code Inspection for Bug 245698

In the past two weeks, to locate the code which causes the bug, I have checked out org.eclipse.wst.sse.core, org.eclipse.wst.xml.core, org.eclipse.wst.sse.ui, and org.eclipse.wst.xml.ui. I started with searching for the radio button label "Create XML file from an XML schema file" in new XML wizard. Then I found out the source code for creating a New XML schema Wizard window in org.eclipse.wst.xml.ui - NewXMLWizard.java.
In NewXMLWizard.java, there is a fuction called perfromFinish(), and here is its signature public boolean performFinish(). Within the function is the code doing the background processes when the "Finish" button on the New XML Wizard is clicked. In performFinish(), I found the following code handling the creation of a new xml document.

if (getContainer().getCurrentPage() == selectRootElementPage) {
generator.createXMLDocument(newFile, xmlFileName);
}
else {
// put template contents into file
String templateString = fNewXMLTemplatesWizardPage.getTemplateString();
generator.createTemplateXMLDocument(newFile, templateString);
}

So, I inserted a break point in the first line of the above code, debugged eclipse-wtp, and reproduced the bug. When the break point was hit, it met the codition in the if statement, and called createXMLDocument(). Then I looked up the type of generator, and found the type of it is NewXMLGenerator. NewXMLGenerator.java is in also in org.eclipse.wst.xml.ui. Then, I checked out createXMLDocument() in org.eclipse.wst.xml.ui. createXMLDocument is overloaded with three different signatures. The one called from NewXMLWizard.java is public ByteArrayOutputStream createXMLDocument(String xmlFileName, String charset) throws Exception. Basically, the createXMLDocument() is responsible for creating the XML document from the XML schema and then put the content of the newly created XML document into a file named by the user with an output stream, The following line in createXMLDocument is doing the job of creating a new XML document based on a XML schema.

DOMContentBuilderImpl contentBuilder = new DOMContentBuilderImpl(xmlDocument);

So, in the following week, I will look more into DOMContentBuilderImpl...

Saturday, July 4, 2009

Cause of Eclipse WTP Bug #245698

After I reproduced the bug successfully, I started to look into the reason why the newly created XML file did not pass the validation. Here is a screen shot of the XML file generated from web-jsptaglibrary_2_1.xsd:



In the screen shot, notice that there are 26 errors in the XML file, and the major one is "cvc-complex-type.3.2.2: Attribute 'javaee:lang' is not allowed to appear in element 'javaee:description'", which applied to all <javaee:description>, <javaee:display-name>, and <javaee:icon tags in the XML file>.

What this error mean is javaee:lang is not a valid attribute inside <javaee:description>, <javaee:display-name>, and <javeee:icon>. So, I checked out the XML schema definition file web-jsptaglibrary_2_1.xsd.

Lines in between <xsd:complexType name="tldTagLibType"\> and its corresponding </xsd:complexType> is the type definition for tldTagLibType - type of taglib. Those lines are saying taglib can the following child tags in sequence: description(optional), display-name, icon(optional), tlib-version, short-name, uri, validator, listener(optional), tag(optional), tag-file, function, and tablib-extension. And also, description, display-name, and icon are grouped together and defined as "descriptionGroup".

So, to check out the definition for <javaee:description>, <javaee:display-name>, and <javaee:icon>, I first found XML schema definition file in which "descriptionGroup" is defined, and it is javaee_5.xsd. Surprisingly, the definition of descriptionGroup, description, display-name, and icon are all in javaee_5.xsd.

descriptionGroup:


descriptionType:


After checking out the definition for descriptionType, I found out that the correct prefix for lang attribute inside <javaee:description> should be xml, rather that javaee, which is also true to <javaee:display-name> and <javaee:icon>.

Then, I tried to changed all javaee:lang inside <javaee:description>, <javaee:display-name>, and <javaee:icon> of the XML file generated from web-jsptaglibrary_2_1.xsd to xml:lang. Compared to the previous screen shot on the newly created XML file. All "cvc-complex-type.3.2.2: Attribute 'javaee:lang' is not allowed to appear in element 'javaee:description'" are gone.



So, the cause of this bug is the prefix for the lang attribute inside <javaee:description>, <javaee:display-name>, and <javaee:icon> is not configured correctly.

Thursday, July 2, 2009

Solution to "java.lang.OutOfMemoryError: PermGen space"

I was trying to debug Eclipse WTP with Eclipse for RCP to locate the code causing the bug I mentioned in the previous post. When the break point inserted was hit, it returned such as error "java.lang.OutOfMemoryError: PermGen space" in the console window of Eclipse for RCP.

I googled the error message for solutions, and find the following link, http://www.freshblurbs.com/explaining-java-lang-outofmemoryerror-permgen-space, has a detailed explanation on what exactly this error is and the cause of the error.

The easiest way to solve this problem is to increase the maximum size of PermGen space. You can change the size of PermGen space by either editing eclipse.ini of Eclipse Web Tools Platform or specifying the JVM memory settings of Eclipse for RCP.

To change the maximum size of PermGen space through eclipse.ini of Eclipse Web Tools Platform, navigate to the folder where WTP is installed. Then you will find a file called "eclipse.ini" similar to this:



What you need to do is to add the following line to the end of the file:
-XX:MaxPermSize=128m (not necessarily 128m, default is 64m)

To change the maximum size of PermGen space on Eclipse memory settings of JVM, Click on Run/Debug Configurations... under Run menu. Then the Run/Debug Configurations... window pops up. On the left panel of Run/Debug Configurations... window, expand "Eclipse Application" and select new configuration. (If you do not see any configuration, create a new one by right clicking on "Eclipse Application" and select "New" from the context menu). On the right panel of Run/Debug Configurations... window, click on the argument tab, put the following line into the text box for "VMarguments":
-XX:MaxPermSize=128m

Click on Run/Debug at the bottom.

Monday, June 29, 2009

OSD 700 Project - Bug 245698

Steps to reproduce Bug 245698:


Step 1: Open Eclipse WTP, click "File" on menu bar, select "New", and click on "Dynamic Web Project" from the drilled down menu.
If "Dynamic Web Project" is not available from the drilled down menu, click on "Others..." on the drilled down menu to get a detailed list of all the projects and then select "Dynamic Web Project".




Step 2:
Configure the settings for the dynamic web project. (Project Name, Target Runtime...)
Then, click on "Finish".




Step 3:
Once the project is created, right click on the name of the project under "Project Explorer", and move the mouse over "New" on the context menu. Click on "XML" on the drilled down menu for "New"




Step 4:
a) When the XML wizard is started, a window title "New XML File" will be open. Accept the default file name for the new XML file, click on "Next".

b) In the Next Step of XML wizard, select "create XML file from an XML schema file", click on "Next".

c) Then, you will need to choose an XML scheme from which you will create you XML file. When you click on the radio button for "Select XML catalog entry", the window will be filled up with a list of XML schema files with a pair of key and URI. Select the XML schema file with the key value of "http://java.sun.com/xml/ns/javaee/web-jsptagliarary_2_1.xsd", then click on "Next".

d) Leave the root element as "taglib" in the next step, check "Create optional attributes" and "Create optional elements", then click on "Finish".

4.a


4.b


4.c


4.d



Step 5:
Now you will see a newly created XML with 26 errors. Bug is reproduced successfully!