/*
* $Header: /home/cvs/jakarta-slide/src/share/org/apache/slide/common/XMLUnmarshaller.java,v 1.26.2.3 2004/03/29 12:35:33 unico Exp $
* $Revision: 1.26.2.3 $
* $Date: 2004/03/29 12:35:33 $
*
* ====================================================================
*
* Copyright 1999-2002 The Apache Software Foundation
*
* 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 org.apache.slide.common;
import java.io.IOException;
import java.io.StringReader;
import java.util.Enumeration;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.apache.slide.content.NodeProperty;
import org.apache.slide.content.NodeRevisionContent;
import org.apache.slide.content.NodeRevisionDescriptor;
import org.apache.slide.content.NodeRevisionDescriptors;
import org.apache.slide.content.RevisionAlreadyExistException;
import org.apache.slide.content.RevisionContentNotFoundException;
import org.apache.slide.content.RevisionDescriptorNotFoundException;
import org.apache.slide.content.RevisionNotFoundException;
import org.apache.slide.lock.ObjectLockedException;
import org.apache.slide.security.AccessDeniedException;
import org.apache.slide.security.NodePermission;
import org.apache.slide.structure.ActionNode;
import org.apache.slide.structure.LinkNode;
import org.apache.slide.structure.LinkedObjectNotFoundException;
import org.apache.slide.structure.ObjectAlreadyExistsException;
import org.apache.slide.structure.ObjectNode;
import org.apache.slide.structure.ObjectNotFoundException;
import org.apache.slide.structure.SubjectNode;
import org.apache.slide.util.conf.Configuration;
import org.apache.slide.util.conf.ConfigurationElement;
import org.apache.slide.util.conf.ConfigurationException;
import org.apache.slide.util.conf.Populate;
import org.apache.slide.util.logger.Logger;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
* XMLUnmarshaller class.
*
* @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
* @version $Revision: 1.26.2.3 $
*/
public final class XMLUnmarshaller {
private final static String LOG_CHANNEL = XMLUnmarshaller.class.getName();
// --------------------------------------------------------- Public Methods
/**
* Import data from Avalon configuration object.
*
* @param token CredentialsToken, used for access to the namespace
* @param dataConfiguration Configuration object
* @exception ConfigurationException Something went wrong during the
* reading of the XML
* @exception UnknownObjectClassException Object class not found
* @exception ServiceAccessException Error accessing service
*/
public static void unmarshal(NamespaceAccessToken accessToken,
SlideToken token,
Configuration dataConfiguration)
throws ConfigurationException, UnknownObjectClassException,
ServiceAccessException {
loadObjectNode(accessToken, token,
dataConfiguration.getConfiguration("objectnode"));
}
// -------------------------------------------------------- Private Methods
/**
* Loads a Slide Object.
*
* @param token Credentials token
* @param objectDefinition Configuration object
* @exception ServiceAccessException Object creation failed because
* a data access error occured
* @exception UnknownObjectClassException Object class not found
* @exception ConfigurationException Something went wrong during the
* reading of the XML
*/
private static void loadObjectNode
(NamespaceAccessToken accessToken, SlideToken token,
Configuration objectDefinition)
throws ServiceAccessException, ConfigurationException,
UnknownObjectClassException {
String className = objectDefinition.getAttribute("classname");
String uri = objectDefinition.getAttribute("uri");
accessToken.getLogger().log("Loading object " + uri,
LOG_CHANNEL,Logger.INFO);
try {
Class objectClass = null;
try {
// First, load the object's class
objectClass = Class.forName(className);
} catch (ClassNotFoundException e) {
// Class loading failed : The requested class was not found
// We throw an exception and interrupt the loading of the file.
throw new UnknownObjectClassException(className);
}
ObjectNode object = null;
try {
// Get a new instance of the class
object = (ObjectNode) objectClass.newInstance();
} catch(InstantiationException e) {
// Instantiation failed for some reason
throw new UnknownObjectClassException(className);
} catch(IllegalAccessException e) {
// The initializer could not be called because
// of access restrictions
throw new UnknownObjectClassException(className);
}
if (uri.equals("/")) {
// FIXME
} else {
try {
if (object instanceof LinkNode) {
String linkedUri =
objectDefinition.getAttribute("linkedUri");
accessToken.getStructureHelper().createLink
(token, (LinkNode) object, uri,
new SubjectNode(linkedUri));
} else {
accessToken.getStructureHelper().create
(token, object, uri);
}
} catch (ObjectAlreadyExistsException e) {
// Ignore, log and continue
accessToken.getLogger().log
("Object already exists at " + uri,
LOG_CHANNEL, Logger.INFO);
}
}
// Retrieving the list of permissions on the object
Enumeration permissionDefinitions =
objectDefinition.getConfigurations("permission");
// We've made sure that the object exists.
// We now parse the permissions definition list, adding each
// permission to the object's permission list.
while (permissionDefinitions.hasMoreElements()) {
Configuration permissionDefinition =
(Configuration) permissionDefinitions.nextElement();
// Create the NodePermission object matching the Castor object
String subjectUri =
permissionDefinition.getAttribute("subject");
if (accessToken.getNamespaceConfig().getUsersPath().equals(subjectUri)) {
subjectUri = SubjectNode.ALL_URI;
}
else if (SubjectNode.ALL_URI.equals(subjectUri)) {
subjectUri = SubjectNode.ALL_URI;
}
else if (SubjectNode.OWNER_URI.equals(subjectUri)) {
subjectUri = SubjectNode.OWNER_URI;
}
else if (SubjectNode.UNAUTHENTICATED_URI.equals(subjectUri)) {
subjectUri = SubjectNode.UNAUTHENTICATED_URI;
}
else if (SubjectNode.AUTHENTICATED_URI.equals(subjectUri)) {
subjectUri = SubjectNode.AUTHENTICATED_URI;
}
else if (SubjectNode.SELF_URI.equals(subjectUri)) {
subjectUri = SubjectNode.SELF_URI;
}
String actionUri =
permissionDefinition.getAttribute("action");
if (accessToken.getNamespaceConfig().getActionsPath().equals(actionUri)) {
actionUri = ActionNode.ALL_URI;
}
else if (ActionNode.ALL_URI.equals(actionUri)) {
actionUri = ActionNode.ALL_URI;
}
boolean inheritable = true;
try {
if (permissionDefinition.getAttribute("inheritable")
.equals("false")) {
inheritable = false;
}
} catch (ConfigurationException e) {
}
boolean negative = false;
try {
if (permissionDefinition.getAttribute("negative")
.equals("true")) {
negative = true;
}
} catch (ConfigurationException e) {
}
NodePermission permission = new NodePermission
(uri, subjectUri, actionUri, inheritable, negative);
// Adding the NodePermission to the ObjectNode
accessToken.getSecurityHelper()
.grantPermission(token, permission);
}
// Retrieve the list of revisions of the object
Enumeration revisionDefinitions =
objectDefinition.getConfigurations("revision");
boolean revisionDefinitionsFound = false;
// We parse the revision definition list
while (revisionDefinitions.hasMoreElements()) {
revisionDefinitionsFound = true;
Configuration revisionDefinition =
(Configuration) revisionDefinitions.nextElement();
loadObjectRevision(accessToken, token, uri,
revisionDefinition);
}
if (!revisionDefinitionsFound) {
loadDefaultObjectRevision(accessToken, token, uri);
}
} catch (ObjectNotFoundException e) {
// Should NEVER happen
accessToken.getLogger().log(e,LOG_CHANNEL,Logger.WARNING);
accessToken.getLogger().log
(e.toString(),LOG_CHANNEL,Logger.WARNING);
} catch (LinkedObjectNotFoundException e) {
// Icorrect link
accessToken.getLogger().log(e,LOG_CHANNEL,Logger.WARNING);
accessToken.getLogger().log
("Incorrect link found while creating " + uri,
LOG_CHANNEL,Logger.WARNING);
} catch (AccessDeniedException e) {
// Security exception
accessToken.getLogger().log
("Insufficient credentials to create object",
LOG_CHANNEL,Logger.INFO);
} catch (ObjectLockedException e) {
// Lock exception
accessToken.getLogger().log
("Lock-Token required",
LOG_CHANNEL,Logger.INFO);
}
Enumeration childConfigurations =
objectDefinition.getConfigurations("objectnode");
while(childConfigurations.hasMoreElements()) {
Configuration childConfiguration =
(Configuration) childConfigurations.nextElement();
loadObjectNode(accessToken, token, childConfiguration);
}
}
/**
* Create the SlideProperties object associated with a ObjectNode.
*
* @param slideObject ObjectNode
* @param propertiesDef Castor object describing the properties associated
* with the ObjectNode
* @exception SlideException A data access error occured
*/
private static void loadDefaultObjectRevision(NamespaceAccessToken accessToken,
SlideToken token, String uri)
throws ServiceAccessException, ConfigurationException,
AccessDeniedException, ObjectNotFoundException,
LinkedObjectNotFoundException {
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(false);
factory.setValidating(false);
SAXParser parser = factory.newSAXParser();
Populate pop = new Populate();
Configuration slideConfiguration =
new ConfigurationElement(
pop.load(
new InputSource(
new StringReader("<revision/>")), parser.getXMLReader()));
loadObjectRevision(accessToken, token, uri, slideConfiguration);
}
catch (IOException e) { e.printStackTrace(); }
catch (SAXException e) { e.printStackTrace(); }
catch (javax.xml.parsers.ParserConfigurationException e) {e.printStackTrace(); }
}
/**
* Create the SlideProperties object associated with a ObjectNode.
*
* @param slideObject ObjectNode
* @param propertiesDef Castor object describing the properties associated
* with the ObjectNode
* @exception SlideException A data access error occured
*/
private static void loadObjectRevision(NamespaceAccessToken accessToken,
SlideToken token, String uri,
Configuration revisionDefinition)
throws ServiceAccessException, ConfigurationException,
AccessDeniedException, ObjectNotFoundException,
LinkedObjectNotFoundException {
// Retrieving the list of properties
Enumeration propertyDefinitions =
revisionDefinition.getConfigurations("property");
// Now creating the new revision descriptor object
NodeRevisionDescriptor revisionDescriptor = null;
NodeRevisionDescriptors revisionDescriptors = null;
try {
revisionDescriptors = accessToken.getContentHelper().retrieve
(token, uri);
} catch (ObjectLockedException e) {
// Ignore
}
if ((revisionDescriptors != null)
&& (revisionDescriptors.hasRevisions())) {
try {
revisionDescriptor = accessToken.getContentHelper().retrieve
(token, revisionDescriptors);
} catch (RevisionDescriptorNotFoundException e) {
// Ignore
} catch (ObjectLockedException e) {
// Ignore
}
}
if (revisionDescriptor == null) {
revisionDescriptor = new NodeRevisionDescriptor(0);
}
while (propertyDefinitions.hasMoreElements()) {
Configuration propertyDefinition =
(Configuration) propertyDefinitions.nextElement();
String propertyName = propertyDefinition.getAttribute("name");
String propertyValue = propertyDefinition.getValue();
String propertyNamespace = propertyDefinition.getAttribute
("namespace", NodeProperty.DEFAULT_NAMESPACE);
NodeProperty property = revisionDescriptor.getProperty
(propertyName, propertyNamespace);
if (property == null)
revisionDescriptor.setProperty(propertyName, propertyNamespace,
propertyValue);
}
NodeRevisionContent revisionContent = null;
if ((revisionDescriptors != null)
&& (revisionDescriptors.hasRevisions())) {
try {
revisionContent = accessToken.getContentHelper()
.retrieve(token, uri, revisionDescriptor);
} catch (RevisionContentNotFoundException e) {
// Ignore
} catch (ObjectLockedException e) {
// Ignore
} catch (RevisionNotFoundException e) {
// No content for this revision
}
try {
accessToken.getContentHelper().store
(token, uri, revisionDescriptor, revisionContent);
} catch (RevisionDescriptorNotFoundException e) {
// Should not happen
accessToken.getLogger().log(e,LOG_CHANNEL,Logger.WARNING);
accessToken.getLogger().log
(e.toString(),LOG_CHANNEL,Logger.WARNING);
} catch (RevisionNotFoundException e) {
// Should not happen
accessToken.getLogger().log(e,LOG_CHANNEL,Logger.WARNING);
accessToken.getLogger().log
(e.toString(),LOG_CHANNEL,Logger.WARNING);
} catch (ObjectLockedException e) {
// Ignore
}
} else {
try {
accessToken.getContentHelper().create
(token, uri, revisionDescriptor, revisionContent);
} catch(ObjectLockedException e) {
// Should not happen
accessToken.getLogger().log(e,LOG_CHANNEL,Logger.WARNING);
accessToken.getLogger().log
(e.toString(),LOG_CHANNEL,Logger.WARNING);
} catch(RevisionAlreadyExistException e) {
// Should not happen
accessToken.getLogger().log(e,LOG_CHANNEL,Logger.WARNING);
accessToken.getLogger().log
(e.toString(),LOG_CHANNEL,Logger.WARNING);
}
}
}
}