Index: components/page-manager/src/test/org/apache/jetspeed/page/TestCastorXmlPageManager.java
===================================================================
--- components/page-manager/src/test/org/apache/jetspeed/page/TestCastorXmlPageManager.java (revision 548244)
+++ components/page-manager/src/test/org/apache/jetspeed/page/TestCastorXmlPageManager.java (working copy)
@@ -28,6 +28,7 @@
import junit.framework.TestCase;
import junit.framework.TestSuite;
+import org.apache.commons.collections.CollectionUtils;
import org.apache.jetspeed.JetspeedActions;
import org.apache.jetspeed.om.common.GenericMetadata;
import org.apache.jetspeed.om.common.SecurityConstraint;
@@ -967,4 +968,34 @@
// TODO: menu testing
}
+
+ public Collection collectIds(Fragment f){
+ Collection result = new ArrayList();
+
+ result.add(f.getId());
+ if (f.getFragments().size() > 0){
+ for (Iterator iter = f.getFragments().iterator(); iter.hasNext();) {
+ Fragment child = (Fragment) iter.next();
+ result.addAll(collectIds(child));
+ }
+ }
+ return result;
+ }
+
+ public void testIdGeneration() throws Exception{
+ Page pageNoIds = pageManager.getPage("/pageWithoutIds.psml");
+ assertNotNull(pageNoIds);
+ Page pageSomeIds = pageManager.getPage("/pageWithSomeIds.psml");
+ assertNotNull(pageSomeIds);
+
+ Collection allIds = collectIds(pageNoIds.getRootFragment());
+ allIds.addAll(collectIds(pageSomeIds.getRootFragment()));
+ for (Iterator iter = allIds.iterator(); iter.hasNext();) {
+ String id = (String) iter.next();
+ assertNotNull(id);
+ assertEquals(true,id.length() > 0);
+ assertEquals(1, CollectionUtils.cardinality(id, allIds)); // uniqueness test
+ }
+ }
+
}
Index: components/page-manager/src/java/org/apache/jetspeed/om/page/psml/FragmentImpl.java
===================================================================
--- components/page-manager/src/java/org/apache/jetspeed/om/page/psml/FragmentImpl.java (revision 548244)
+++ components/page-manager/src/java/org/apache/jetspeed/om/page/psml/FragmentImpl.java (working copy)
@@ -36,6 +36,8 @@
public class FragmentImpl extends AbstractBaseElement implements Fragment, java.io.Serializable
{
+ private static int fragment_id_counter = 0;
+
private String type = null;
private String state = null;
@@ -69,6 +71,15 @@
{
}
+ public FragmentImpl(String id)
+ {
+ if (id == null || id.length() == 0){
+ setId(generateId());
+ } else {
+ setId(id);
+ }
+ }
+
public String getType()
{
return this.type;
@@ -689,4 +700,8 @@
}
return fragments;
}
+
+ private synchronized static String generateId(){
+ return new StringBuffer("F.").append(Long.toHexString(System.currentTimeMillis())).append(".").append(fragment_id_counter++).toString();
+ }
}
Index: components/page-manager/src/java/org/apache/jetspeed/page/document/psml/CastorFileSystemDocumentHandler.java
===================================================================
--- components/page-manager/src/java/org/apache/jetspeed/page/document/psml/CastorFileSystemDocumentHandler.java (revision 548244)
+++ components/page-manager/src/java/org/apache/jetspeed/page/document/psml/CastorFileSystemDocumentHandler.java (working copy)
@@ -49,20 +49,25 @@
import org.apache.xml.serialize.OutputFormat;
import org.apache.xml.serialize.Serializer;
import org.apache.xml.serialize.XMLSerializer;
+import org.castor.mapping.BindingType;
+import org.castor.mapping.MappingUnmarshaller;
import org.exolab.castor.mapping.Mapping;
import org.exolab.castor.mapping.MappingException;
-import org.exolab.castor.xml.EventProducer;
+import org.exolab.castor.mapping.MappingLoader;
+import org.exolab.castor.xml.ClassDescriptorResolver;
+import org.exolab.castor.xml.ClassDescriptorResolverFactory;
import org.exolab.castor.xml.MarshalException;
import org.exolab.castor.xml.Marshaller;
+import org.exolab.castor.xml.SAX2EventProducer;
import org.exolab.castor.xml.Unmarshaller;
import org.exolab.castor.xml.ValidationException;
-import org.xml.sax.AttributeList;
-import org.xml.sax.DocumentHandler;
+import org.exolab.castor.xml.XMLClassDescriptorResolver;
+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.XMLReader;
-import org.xml.sax.helpers.XMLReaderAdapter;
/**
*
@@ -81,19 +86,16 @@
private final static Log log = LogFactory.getLog(CastorFileSystemDocumentHandler.class);
private final static String PSML_DOCUMENT_ENCODING = "UTF-8";
-
- protected String mappingFile;
protected String documentType;
protected Class expectedReturnType;
protected String documentRoot;
protected File documentRootDir;
protected FileCache fileCache;
- /** the Castor mapping file name */
- protected Mapping mapping = null;
-
+
private OutputFormat format;
-
+ private final XMLReader xmlReader;
private DocumentHandlerFactory handlerFactory;
+ private ClassDescriptorResolver classDescriptorResolver;
/**
*
@@ -105,10 +107,9 @@
* @throws FileNotFoundException
*/
public CastorFileSystemDocumentHandler( String mappingFile, String documentType, Class expectedReturnType,
- String documentRoot, FileCache fileCache ) throws FileNotFoundException
+ String documentRoot, FileCache fileCache ) throws FileNotFoundException,SAXException,ParserConfigurationException, MappingException
{
super();
- this.mappingFile = mappingFile;
this.documentType = documentType;
this.expectedReturnType = expectedReturnType;
this.documentRoot = documentRoot;
@@ -120,12 +121,22 @@
format.setIndenting(true);
format.setIndent(4);
format.setEncoding(PSML_DOCUMENT_ENCODING);
-
- loadMapping();
+
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ SAXParser parser = factory.newSAXParser();
+
+ xmlReader = parser.getXMLReader();
+ xmlReader.setFeature("http://xml.org/sax/features/namespaces", true);
+
+ /*
+ * Create ClassDescripterResolver for better performance.
+ * Mentioned as 'best practice' on the Castor website.
+ */
+ createCastorClassDescriptorResolver(mappingFile);
}
public CastorFileSystemDocumentHandler( String mappingFile, String documentType, String expectedReturnType,
- String documentRoot, FileCache fileCache ) throws FileNotFoundException, ClassNotFoundException
+ String documentRoot, FileCache fileCache ) throws FileNotFoundException, ClassNotFoundException,SAXException,ParserConfigurationException, MappingException
{
this(mappingFile, documentType, Class.forName(expectedReturnType), documentRoot, fileCache);
}
@@ -191,17 +202,18 @@
try
{
- // marshal: use SAX I handler to filter document XML for
+ // marshal: use SAX II handler to filter document XML for
// page and folder menu definition menu elements ordered
// polymorphic collection to strip artifical
// tags enabling Castor XML binding; see JETSPEED-INF/castor/page-mapping.xml
writer = new OutputStreamWriter(new FileOutputStream(f), PSML_DOCUMENT_ENCODING);
Serializer serializer = new XMLSerializer(writer, this.format);
- final DocumentHandler handler = serializer.asDocumentHandler();
- Marshaller marshaller = new Marshaller(new DocumentHandler()
+ final ContentHandler handler = serializer.asContentHandler();
+
+ Marshaller marshaller = new Marshaller(new ContentHandler()
{
private int menuDepth = 0;
-
+
public void characters(char[] ch, int start, int length) throws SAXException
{
handler.characters(ch, start, length);
@@ -212,21 +224,6 @@
handler.endDocument();
}
- public void endElement(String name) throws SAXException
- {
- // track menu depth
- if (name.equals("menu"))
- {
- menuDepth--;
- }
-
- // filter menu-element noded within menu definition
- if ((menuDepth == 0) || !name.equals("menu-element"))
- {
- handler.endElement(name);
- }
- }
-
public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException
{
handler.ignorableWhitespace(ch, start, length);
@@ -247,22 +244,49 @@
handler.startDocument();
}
- public void startElement(String name, AttributeList atts) throws SAXException
- {
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+ // track menu depth
+ if (localName.equals("menu"))
+ {
+ menuDepth--;
+ }
+
// filter menu-element noded within menu definition
- if ((menuDepth == 0) || !name.equals("menu-element"))
+ if ((menuDepth == 0) || !localName.equals("menu-element"))
{
- handler.startElement(name, atts);
+ handler.endElement(uri, localName, qName);
}
+ }
+ public void endPrefixMapping(String prefix) throws SAXException {
+ handler.endPrefixMapping(prefix);
+ }
+
+ public void skippedEntity(String name) throws SAXException {
+ handler.skippedEntity(name);
+ }
+
+ public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
+ // filter menu-element noded within menu definition
+ if ((menuDepth == 0) || !localName.equals("menu-element"))
+ {
+ handler.startElement(uri,localName, qName, atts);
+ }
+
// track menu depth
- if (name.equals("menu"))
+ if (localName.equals("menu"))
{
menuDepth++;
}
- }
+ }
+
+ public void startPrefixMapping(String prefix, String uri) throws SAXException {
+ handler.startPrefixMapping(prefix, uri);
+ }
});
- marshaller.setMapping(this.mapping);
+ marshaller.setResolver((XMLClassDescriptorResolver) classDescriptorResolver);
+
+ marshaller.setValidation(false); // results in better performance
marshaller.marshal(document);
}
catch (MarshalException e)
@@ -270,11 +294,6 @@
log.error("Could not marshal the file " + f.getAbsolutePath(), e);
throw new FailedToUpdateDocumentException(e);
}
- catch (MappingException e)
- {
- log.error("Could not marshal the file " + f.getAbsolutePath(), e);
- throw new FailedToUpdateDocumentException(e);
- }
catch (ValidationException e)
{
log.error("Document " + f.getAbsolutePath() + " is not valid", e);
@@ -303,11 +322,10 @@
}
-
-
- protected void loadMapping()
+ protected void createCastorClassDescriptorResolver(String mappingFile) throws MappingException
{
- try
+ Mapping mapping=null;
+ try
{
InputStream stream = getClass().getResourceAsStream(mappingFile);
@@ -329,7 +347,11 @@
ise.initCause(e);
throw ise;
}
-
+ this.classDescriptorResolver =
+ ClassDescriptorResolverFactory.createClassDescriptorResolver(BindingType.XML);
+ MappingUnmarshaller mappingUnmarshaller = new MappingUnmarshaller();
+ MappingLoader mappingLoader = mappingUnmarshaller.getMappingLoader(mapping, BindingType.XML);
+ classDescriptorResolver.setMappingLoader(mappingLoader);
}
protected Object unmarshallDocument( Class clazz, String path, String extension ) throws DocumentNotFoundException,
@@ -353,21 +375,20 @@
try
{
- // unmarshal: use SAX I parser to read document XML, filtering
+ // unmarshal: use SAX II parser to read document XML, filtering
// for page and folder menu definition menu elements ordered
// polymorphic collection to insert artifical
// tags enabling Castor XML binding; see JETSPEED-INF/castor/page-mapping.xml
- SAXParserFactory factory = SAXParserFactory.newInstance();
- SAXParser parser = factory.newSAXParser();
- XMLReader reader = parser.getXMLReader();
- final XMLReaderAdapter readerAdapter = new XMLReaderAdapter(reader);
+
final InputSource readerInput = new InputSource(new InputStreamReader(new FileInputStream(f), PSML_DOCUMENT_ENCODING));
- Unmarshaller unmarshaller = new Unmarshaller(this.mapping);
- document = (Document) unmarshaller.unmarshal(new EventProducer()
+ Unmarshaller unmarshaller = new Unmarshaller();
+ unmarshaller.setResolver((XMLClassDescriptorResolver) classDescriptorResolver);
+ unmarshaller.setValidation(false); // results in better performance
+ document = (Document) unmarshaller.unmarshal(new SAX2EventProducer()
{
- public void setDocumentHandler(final DocumentHandler handler)
+ public void setContentHandler(final ContentHandler handler)
{
- readerAdapter.setDocumentHandler(new DocumentHandler()
+ xmlReader.setContentHandler(new ContentHandler()
{
private int menuDepth = 0;
@@ -381,30 +402,6 @@
handler.endDocument();
}
- public void endElement(String name) throws SAXException
- {
- // always include all elements
- handler.endElement(name);
-
- // track menu depth and insert menu-element nodes
- // to encapsulate menu elements to support collection
- // polymorphism in Castor
- if (name.equals("menu"))
- {
- menuDepth--;
- if (menuDepth > 0)
- {
- handler.endElement("menu-element");
- }
- }
- else if ((menuDepth > 0) &&
- (name.equals("options") || name.equals("separator") ||
- name.equals("include") || name.equals("exclude")))
- {
- handler.endElement("menu-element");
- }
- }
-
public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException
{
handler.ignorableWhitespace(ch, start, length);
@@ -425,36 +422,72 @@
handler.startDocument();
}
- public void startElement(String name, AttributeList atts) throws SAXException
- {
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+// always include all elements
+ uri=""; // strip namespaces
+
+ handler.endElement(uri,localName,qName);
// track menu depth and insert menu-element nodes
// to encapsulate menu elements to support collection
// polymorphism in Castor
- if (name.equals("menu"))
+ if (localName.equals("menu"))
{
+ menuDepth--;
if (menuDepth > 0)
{
- handler.startElement("menu-element", null);
+ handler.endElement(uri,"menu-element","menu-element");
}
+ }
+ else if ((menuDepth > 0) &&
+ (localName.equals("options") || localName.equals("separator") ||
+ localName.equals("include") || localName.equals("exclude")))
+ {
+ handler.endElement(uri,"menu-element","menu-element");
+ }
+ }
+
+ public void endPrefixMapping(String prefix) throws SAXException {
+ handler.endPrefixMapping(prefix);
+ }
+
+ public void skippedEntity(String name) throws SAXException {
+ handler.skippedEntity(name);
+ }
+
+ public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
+ // track menu depth and insert menu-element nodes
+ // to encapsulate menu elements to support collection
+ // polymorphism in Castor
+ uri=""; // strip namespaces
+ if (localName.equals("menu"))
+ {
+ if (menuDepth > 0)
+ {
+ handler.startElement(uri,"menu-element","menu-element", null);
+ }
menuDepth++;
}
else if ((menuDepth > 0) &&
- (name.equals("options") || name.equals("separator") ||
- name.equals("include") || name.equals("exclude")))
+ (localName.equals("options") || localName.equals("separator") ||
+ localName.equals("include") || localName.equals("exclude")))
{
- handler.startElement("menu-element", null);
+ handler.startElement(uri,"menu-element","menu-element", null);
}
// always include all elements
- handler.startElement(name, atts);
- }
+ handler.startElement(uri,localName, qName, atts);
+ }
+
+ public void startPrefixMapping(String prefix, String uri) throws SAXException {
+ handler.startPrefixMapping(prefix, uri);
+ }
});
}
public void start() throws SAXException
{
try
{
- readerAdapter.parse(readerInput);
+ xmlReader.parse(readerInput);
}
catch (IOException ioe)
{
@@ -480,26 +513,11 @@
log.error("Could not unmarshal the file " + f.getAbsolutePath(), e);
throw new PageNotFoundException("Could not unmarshal the file " + f.getAbsolutePath(), e);
}
- catch (MappingException e)
- {
- log.error("Could not unmarshal the file " + f.getAbsolutePath(), e);
- throw new PageNotFoundException("Could not unmarshal the file " + f.getAbsolutePath(), e);
- }
catch (ValidationException e)
{
log.error("Document " + f.getAbsolutePath() + " is not valid", e);
throw new DocumentNotFoundException("Document " + f.getAbsolutePath() + " is not valid", e);
}
- catch (SAXException e)
- {
- log.error("Could not unmarshal the file " + f.getAbsolutePath(), e);
- throw new PageNotFoundException("Could not unmarshal the file " + f.getAbsolutePath(), e);
- }
- catch (ParserConfigurationException e)
- {
- log.error("Could not unmarshal the file " + f.getAbsolutePath(), e);
- throw new PageNotFoundException("Could not unmarshal the file " + f.getAbsolutePath(), e);
- }
if (document == null)
Index: components/page-manager/src/java/JETSPEED-INF/castor/page-mapping.xml
===================================================================
--- components/page-manager/src/java/JETSPEED-INF/castor/page-mapping.xml (revision 548244)
+++ components/page-manager/src/java/JETSPEED-INF/castor/page-mapping.xml (working copy)
@@ -1,5 +1,5 @@
-
castor
-
- 0.9.4.3
+ 1.1.1-xml
true