Index: components/page-manager/project.xml =================================================================== --- components/page-manager/project.xml (revision 551254) +++ components/page-manager/project.xml (working copy) @@ -88,7 +88,8 @@ - **/PageManagerTestShared.java + **/PageManagerTestShared.javav + **/DirectoryXMLTransform.java Index: components/page-manager/src/test/org/apache/jetspeed/page/DirectoryXMLTransform.java =================================================================== --- components/page-manager/src/test/org/apache/jetspeed/page/DirectoryXMLTransform.java (revision 0) +++ components/page-manager/src/test/org/apache/jetspeed/page/DirectoryXMLTransform.java (revision 0) @@ -0,0 +1,205 @@ +/** + * + */ +package org.apache.jetspeed.page; + +import java.io.File; +import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.Writer; +import java.nio.channels.FileChannel; +import java.util.Iterator; +import java.util.Map; + +import javax.xml.parsers.SAXParserFactory; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.sax.SAXTransformerFactory; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; + +import org.apache.commons.lang.StringUtils; +import org.apache.jetspeed.util.DirectoryHelper; + + +/** + * @author ddam + * + */ +public class DirectoryXMLTransform extends DirectoryHelper +{ + private SAXTransformerFactory transformerFactory; + + private SAXParserFactory saxFactory; + + private Map xsltMapping; + + public DirectoryXMLTransform(File base, Map extensionToXslt) { + super(base); + this.xsltMapping=extensionToXslt; + System.setProperty("javax.xml.transform.TransformerFactory", + "org.apache.xalan.processor.TransformerFactoryImpl"); + System.setProperty("javax.xml.parsers.SAXParserFactory", "org.apache.xerces.jaxp.SAXParserFactoryImpl"); + System.setProperty("org.xml.sax.driver", "org.apache.xerces.parsers.SAXParser"); + transformerFactory = (SAXTransformerFactory) TransformerFactory.newInstance(); + saxFactory = SAXParserFactory.newInstance(); + saxFactory.setValidating(false); + + } + + protected void setBaseDirectory(File directory){ + if(!directory.exists()) + { + directory.mkdirs(); + } + + if(!directory.isDirectory()) + { + throw new IllegalArgumentException("DirectoryHelper(File) requires directory not a file."); + } + this.directory = directory; + + } + + private Transformer getXSLTForFile(File f){ + String extension = StringUtils.substringAfterLast(f.getName(),"."); + + if (!StringUtils.isEmpty(extension) && xsltMapping.containsKey(extension.toLowerCase())){ + + Object t_obj = xsltMapping.get(extension.toLowerCase()); + if (t_obj instanceof Transformer){ + return (Transformer)t_obj; + } + if (t_obj instanceof String){ + String t_path = (String) t_obj; + Transformer transformer; + try{ + transformer = transformerFactory.newTransformer(new StreamSource(t_path)); + xsltMapping.put(extension, transformer); + return transformer; + } catch(TransformerConfigurationException e){ + + } + } + } + + return null; + } + + /** + *

+ * copyFrom + *

+ * + * @see org.apache.jetspeed.util.FileSystemHelper#copyFrom(java.io.File, java.io.FileFilter) + * @param directory + * @param fileFilter + * @throws IOException + */ + public void copyFromAndTransform( File srcDirectory, FileFilter fileFilter ) throws IOException + { + if(!srcDirectory.isDirectory()) + { + throw new IllegalArgumentException("DirectoryHelper.copyFrom(File) requires directory not a file."); + } + copyFilesAndTransform(srcDirectory, directory, fileFilter); + + } + + /** + * + *

+ * copyFiles + *

+ * + * @param srcDir Source directory to copy from. + * @param dstDir Destination directory to copy to. + * @throws IOException + * @throws FileNotFoundException + + */ + protected void copyFilesAndTransform(File srcDir, File dstDir, FileFilter fileFilter) throws IOException + { + FileChannel srcChannel = null; + FileChannel dstChannel = null; + + try + { + File[] children = srcDir.listFiles(fileFilter); + for(int i=0; i 0){ + for (Iterator iter = f.getFragments().iterator(); iter.hasNext();) { + Fragment child = (Fragment) iter.next(); + result.addAll(collectIds(child)); + } + } + return result; + } + + private int countFragments(Fragment f){ + int result = 1; + for (Iterator iter = f.getFragments().iterator(); iter.hasNext();) + { + result+=countFragments((Fragment)iter.next()); + } + + return result; + } + + private void compareFolders(Folder folder1, Folder folder2) throws Exception { + for (Iterator iter = folder1.getAll().iterator(); iter.hasNext();) + { + Object obj = iter.next(); + + if (obj instanceof Page){ + Page thisPage = (Page) obj; + Page otherPage = folder2.getPage(thisPage.getName()); + assertEquals(thisPage.getRootFragment()!=null,otherPage.getRootFragment() != null); + if (thisPage.getRootFragment() != null){ + Fragment thisRootFragment = thisPage.getRootFragment(); + Fragment otherRootFragment = otherPage.getRootFragment(); + assertEquals(thisRootFragment.getFragments().size(),otherRootFragment.getFragments().size()); + assertEquals(countFragments(thisRootFragment),countFragments(otherRootFragment)); + } + } else + if (obj instanceof Folder){ + Folder thisFolder = (Folder)obj; + compareFolders(thisFolder, folder2.getFolder(thisFolder.getName())); + } + + } + } + + public void testIdGeneration() throws Exception{ + Folder webappIds = pageManager.getFolder("/webapp-ids"); + Folder webappNoIds = pageManager.getFolder("/webapp-no-ids"); + + compareFolders(webappIds,webappNoIds); + + Collection allIds = collectIds(webappNoIds); + for (Iterator iter = allIds.iterator(); iter.hasNext();) { + String id = (String) iter.next(); + assertNotNull(id); + assertEquals(true,id.length() > 0); + if (CollectionUtils.cardinality(id, allIds) > 1){ + System.out.println("Fragment with id "+id+" has duplicates"); + } + assertEquals(1, CollectionUtils.cardinality(id, allIds)); // uniqueness test + } + } + } Index: components/page-manager/src/test/org/apache/jetspeed/page/PageManagerTestShared.java =================================================================== --- components/page-manager/src/test/org/apache/jetspeed/page/PageManagerTestShared.java (revision 551254) +++ components/page-manager/src/test/org/apache/jetspeed/page/PageManagerTestShared.java (working copy) @@ -27,9 +27,11 @@ import java.security.PrivilegedAction; import java.security.ProtectionDomain; import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.StringTokenizer; @@ -69,7 +71,6 @@ import org.apache.jetspeed.security.impl.PrincipalsSet; import org.apache.jetspeed.security.impl.RolePrincipalImpl; import org.apache.jetspeed.security.impl.UserPrincipalImpl; -import org.apache.jetspeed.util.DirectoryHelper; /** * PageManagerTestShared @@ -95,8 +96,13 @@ static CastorXmlPageManager makeCastorXMLPageManager(String pagesDirName, boolean permissionsEnabled, boolean constraintsEnabled) throws Exception { + Map extensionsToXslt = new HashMap(); + extensionsToXslt.put("psml","resources/stripIds.xslt"); + File pagesDirFile = new File("target/testdata/" + pagesDirName); - DirectoryHelper dirHelper = new DirectoryHelper(pagesDirFile); + + + DirectoryXMLTransform dirHelper = new DirectoryXMLTransform(pagesDirFile,extensionsToXslt); FileFilter noCVSorSVNorBackups = new FileFilter() { public boolean accept( File pathname ) @@ -105,6 +111,18 @@ } }; dirHelper.copyFrom(new File("testdata/" + pagesDirName), noCVSorSVNorBackups); + + // copy documents under webapp/pages folder and strip fragment Ids + File webappDestDirFile = new File("target/testdata/" + pagesDirName+"/webapp-no-ids"); + dirHelper.setBaseDirectory(webappDestDirFile); + File webappPagesDirFile = new File("../../src/webapp/WEB-INF/pages"); + dirHelper.copyFromAndTransform(webappPagesDirFile, noCVSorSVNorBackups); + + // copy documents under webapp/pages folder without transforming them + webappDestDirFile = new File("target/testdata/" + pagesDirName+"/webapp-ids"); + dirHelper.setBaseDirectory(webappDestDirFile); + dirHelper.copyFrom(webappPagesDirFile, noCVSorSVNorBackups); + IdGenerator idGen = new JetspeedIdGenerator(65536,"P-",""); FileCache cache = new FileCache(10, 12); Index: components/page-manager/src/java/org/apache/jetspeed/om/page/ContentPageImpl.java =================================================================== --- components/page-manager/src/java/org/apache/jetspeed/om/page/ContentPageImpl.java (revision 551254) +++ components/page-manager/src/java/org/apache/jetspeed/om/page/ContentPageImpl.java (working copy) @@ -38,7 +38,8 @@ private final Page page; private final Map cachedFragments; private ContentFragment rootContentFragment; - + private boolean dirty=false; + public ContentPageImpl(Page page) { this.page = page; @@ -522,4 +523,13 @@ { page.setVersion(version); } + + public boolean isDirty() { + return dirty; + } + + public void setDirty(boolean dirty) { + this.dirty = dirty; + } + } Index: components/page-manager/src/java/org/apache/jetspeed/om/page/psml/DocumentImpl.java =================================================================== --- components/page-manager/src/java/org/apache/jetspeed/om/page/psml/DocumentImpl.java (revision 551254) +++ components/page-manager/src/java/org/apache/jetspeed/om/page/psml/DocumentImpl.java (working copy) @@ -1,9 +1,9 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 @@ -25,18 +25,20 @@ * Link *

*

- * + * *

+ * * @author Scott T. Weaver * @version $Id: LinkImpl.java 314803 2005-10-12 06:35:19Z rwatler $ - * + * */ public abstract class DocumentImpl extends AbstractNode implements Document { private String version; - - /** + private boolean dirty=false; + + /** * unmarshalled - notification that this instance has been * loaded from the persistent store */ @@ -65,4 +67,13 @@ { this.version = version; } + + public boolean isDirty() { + return dirty; + } + + public void setDirty(boolean dirty) { + this.dirty = dirty; + } + } 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 551254) +++ 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; @@ -60,6 +62,7 @@ private PageImpl page; + private boolean dirty = false; /** *

* Default Constructor. @@ -69,6 +72,16 @@ { } + public FragmentImpl(String id) + { + if (id == null || id.length() == 0){ + setId(generateId()); + dirty=true; + } else { + setId(id); + } + } + public String getType() { return this.type; @@ -468,6 +481,9 @@ { // set page implementation this.page = page; + if (dirty){ + page.setDirty(dirty); + } // propagate to children if (fragments != null) { @@ -689,4 +705,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/impl/DocumentImpl.java =================================================================== --- components/page-manager/src/java/org/apache/jetspeed/page/document/impl/DocumentImpl.java (revision 551254) +++ components/page-manager/src/java/org/apache/jetspeed/page/document/impl/DocumentImpl.java (working copy) @@ -1,9 +1,9 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 @@ -29,6 +29,8 @@ { private String version; + private boolean dirty = false; + public DocumentImpl(SecurityConstraintsImpl constraints) { super(constraints); @@ -64,4 +66,13 @@ { this.version = version; } + + public boolean isDirty() { + return dirty; + } + + public void setDirty(boolean dirty) { + this.dirty = dirty; + } + } Index: components/page-manager/src/java/org/apache/jetspeed/page/document/psml/AbstractNode.java =================================================================== --- components/page-manager/src/java/org/apache/jetspeed/page/document/psml/AbstractNode.java (revision 551254) +++ components/page-manager/src/java/org/apache/jetspeed/page/document/psml/AbstractNode.java (working copy) @@ -50,7 +50,8 @@ private String url; private boolean hidden=false; private String profiledPath; - + private boolean dirty=false; + public AbstractNode() { } @@ -500,4 +501,14 @@ setMetadataFields(metadataFields); } } + + public boolean isDirty() { + return dirty; + } + + public void setDirty(boolean dirty) { + this.dirty=dirty; + } + + } 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 551254) +++ components/page-manager/src/java/org/apache/jetspeed/page/document/psml/CastorFileSystemDocumentHandler.java (working copy) @@ -35,6 +35,7 @@ import org.apache.jetspeed.cache.file.FileCache; import org.apache.jetspeed.cache.file.FileCacheEntry; import org.apache.jetspeed.cache.file.FileCacheEventListener; +import org.apache.jetspeed.om.common.SecurityConstraints; import org.apache.jetspeed.om.folder.psml.FolderImpl; import org.apache.jetspeed.om.page.Document; import org.apache.jetspeed.om.page.psml.AbstractBaseElement; @@ -49,20 +50,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; /** *

@@ -82,18 +88,16 @@ 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 +109,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 +123,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", false); + + /* + * 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); } @@ -146,7 +159,12 @@ { return getDocument(name, true); } - + + public void updateDocument( Document document ) throws FailedToUpdateDocumentException + { + updateDocument(document, false); + } + /** *

* updateDocument @@ -154,8 +172,9 @@ * * @see org.apache.jetspeed.page.document.DocumentHandler#updateDocument(org.apache.jetspeed.om.page.Document) * @param document + * @param systemUpdate */ - public void updateDocument( Document document ) throws FailedToUpdateDocumentException + protected void updateDocument( Document document, boolean systemUpdate) throws FailedToUpdateDocumentException { // sanity checks if (document == null) @@ -176,8 +195,14 @@ } AbstractBaseElement documentImpl = (AbstractBaseElement)document; documentImpl.setHandlerFactory(handlerFactory); - documentImpl.setPermissionsEnabled(handlerFactory.getPermissionsEnabled()); - documentImpl.setConstraintsEnabled(handlerFactory.getConstraintsEnabled()); + if (systemUpdate){ + // on system update: temporarily turn off security + documentImpl.setPermissionsEnabled(false); + documentImpl.setConstraintsEnabled(false); + } else { + documentImpl.setPermissionsEnabled(handlerFactory.getPermissionsEnabled()); + documentImpl.setConstraintsEnabled(handlerFactory.getConstraintsEnabled()); + } documentImpl.marshalling(); // marshal page to disk @@ -191,17 +216,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 +238,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 +258,47 @@ 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 (qName.equals("menu")) + { + menuDepth--; + } + // filter menu-element noded within menu definition - if ((menuDepth == 0) || !name.equals("menu-element")) + if ((menuDepth == 0) || !qName.equals("menu-element")) { - handler.startElement(name, atts); + handler.endElement(uri, localName, qName); } + } + public void endPrefixMapping(String prefix) throws SAXException { + } + + 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) || !qName.equals("menu-element")) + { + handler.startElement(uri,localName, qName, atts); + } + // track menu depth - if (name.equals("menu")) + if (qName.equals("menu")) { menuDepth++; } - } + } + + public void startPrefixMapping(String prefix, String uri) throws SAXException { + } }); - marshaller.setMapping(this.mapping); + marshaller.setResolver((XMLClassDescriptorResolver) classDescriptorResolver); + + marshaller.setValidation(false); // results in better performance marshaller.marshal(document); } catch (MarshalException e) @@ -270,11 +306,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); @@ -292,7 +323,12 @@ } finally { - try + if (systemUpdate){ + // restore permissions / constraints + documentImpl.setPermissionsEnabled(handlerFactory.getPermissionsEnabled()); + documentImpl.setConstraintsEnabled(handlerFactory.getConstraintsEnabled()); + } + try { writer.close(); } @@ -303,11 +339,10 @@ } - - - protected void loadMapping() + protected void createCastorClassDescriptorResolver(String mappingFile) throws MappingException { - try + Mapping mapping=null; + try { InputStream stream = getClass().getResourceAsStream(mappingFile); @@ -329,7 +364,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 +392,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 +419,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 +439,68 @@ 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 + 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 (qName.equals("menu")) { + menuDepth--; if (menuDepth > 0) { - handler.startElement("menu-element", null); + handler.endElement(null,null,"menu-element"); } + } + else if ((menuDepth > 0) && + (qName.equals("options") || qName.equals("separator") || + qName.equals("include") || qName.equals("exclude"))) + { + handler.endElement(null,null,"menu-element"); + } + } + + public void endPrefixMapping(String prefix) throws SAXException { + } + + 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 + + if (qName.equals("menu")) + { + if (menuDepth > 0) + { + handler.startElement(null,null,"menu-element", null); + } menuDepth++; } else if ((menuDepth > 0) && - (name.equals("options") || name.equals("separator") || - name.equals("include") || name.equals("exclude"))) + (qName.equals("options") || qName.equals("separator") || + qName.equals("include") || qName.equals("exclude"))) { - handler.startElement("menu-element", null); + handler.startElement(null,null,"menu-element", null); } // always include all elements - handler.startElement(name, atts); - } + handler.startElement(null,null, qName, atts); + } + + public void startPrefixMapping(String prefix, String uri) throws SAXException { + } }); } public void start() throws SAXException { try { - readerAdapter.parse(readerInput); + xmlReader.parse(readerInput); } catch (IOException ioe) { @@ -469,6 +515,10 @@ documentImpl.setPermissionsEnabled(handlerFactory.getPermissionsEnabled()); documentImpl.setConstraintsEnabled(handlerFactory.getConstraintsEnabled()); documentImpl.unmarshalled(); + if (document.isDirty()){ + updateDocument(document, true); + document.setDirty(false); + } } catch (IOException e) { @@ -480,26 +530,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 551254) +++ components/page-manager/src/java/JETSPEED-INF/castor/page-mapping.xml (working copy) @@ -1,5 +1,5 @@ - 1.0 - - 0.9.4.3 + 1.1.1-xml 2.1_3 1.7.0 20061115 Index: .classpath =================================================================== --- .classpath (revision 551254) +++ .classpath (working copy) @@ -58,7 +58,7 @@ - + @@ -70,6 +70,7 @@ + Index: core-build.xml =================================================================== --- core-build.xml (revision 551254) +++ core-build.xml (working copy) @@ -246,8 +246,7 @@ castor - - 0.9.4.3 + 1.1.1-xml true Index: jetspeed-api/src/java/org/apache/jetspeed/om/page/Document.java =================================================================== --- jetspeed-api/src/java/org/apache/jetspeed/om/page/Document.java (revision 551254) +++ jetspeed-api/src/java/org/apache/jetspeed/om/page/Document.java (working copy) @@ -46,4 +46,27 @@ */ void setVersion(String versionNumber); + /** + *

+ * isDirty + *

+ *

+ * Whether this node is dirty, i.e. should be updated in the persistent store. + *

+ * @param hidden flag + */ + boolean isDirty(); + + /** + *

+ * setDirty + *

+ *

+ * Flag the node as dirty / clean, i.e. should be resp. should not be updated in the persistent store + *

+ * @param hidden flag + */ + + void setDirty(boolean dirty); + } \ No newline at end of file Index: etc/editors/m2.classpath =================================================================== --- etc/editors/m2.classpath (revision 551254) +++ etc/editors/m2.classpath (working copy) @@ -58,7 +58,7 @@ - + Index: etc/editors/2.1.maven2.classpath =================================================================== --- etc/editors/2.1.maven2.classpath (revision 551254) +++ etc/editors/2.1.maven2.classpath (working copy) @@ -58,7 +58,7 @@ - +