/*
* JBoss, Home of Professional Open Source.
* Copyright 2015, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.as.server.parsing;
import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PATH;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RELATIVE_TO;
import static org.jboss.as.controller.parsing.ParseUtils.isNoNamespaceAttribute;
import static org.jboss.as.controller.parsing.ParseUtils.missingRequired;
import static org.jboss.as.controller.parsing.ParseUtils.requireNamespace;
import static org.jboss.as.controller.parsing.ParseUtils.requireNoContent;
import static org.jboss.as.controller.parsing.ParseUtils.unexpectedAttribute;
import static org.jboss.as.controller.parsing.ParseUtils.unexpectedElement;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.xml.stream.XMLStreamException;
import org.jboss.as.controller.descriptions.ModelDescriptionConstants;
import org.jboss.as.controller.logging.ControllerLogger;
import org.jboss.as.controller.parsing.Attribute;
import org.jboss.as.controller.parsing.Element;
import org.jboss.as.controller.parsing.Namespace;
import org.jboss.as.controller.parsing.ParseUtils;
import org.jboss.dmr.ModelNode;
import org.jboss.dmr.Property;
import org.jboss.staxmapper.XMLExtendedStreamReader;
import org.jboss.staxmapper.XMLExtendedStreamWriter;
/**
* Parsing and marshalling logic specific to vault definitions.
*
* The contents of this file have been pulled from {@see CommonXml}, see the commit history of that file for true author
* attribution.
*
* Note: This class is only indented to support versions 1, 2, and 3 of the schema, if later major versions of the schema
* include updates to the types represented by this class then this class should be forked.
*
* @author <a href="mailto:darran.lofthouse@jboss.com">Darran Lofthouse</a>
*/
class PathsXml {
/**
* The restricted path names.
*/
protected static final Set<String> RESTRICTED_PATHS;
static {
final HashSet<String> set = new HashSet<String>(10);
// Define the restricted path names.
set.add("jboss.home");
set.add("jboss.home.dir");
set.add("user.home");
set.add("user.dir");
set.add("java.home");
set.add("jboss.server.base.dir");
set.add("jboss.server.data.dir");
set.add("jboss.server.log.dir");
set.add("jboss.server.temp.dir");
// NOTE we actually don't create services for the following
// however the names remain restricted for use in the configuration
set.add("jboss.modules.dir");
set.add("jboss.server.deploy.dir");
set.add("jboss.domain.servers.dir");
RESTRICTED_PATHS = Collections.unmodifiableSet(set);
}
void parsePaths(final XMLExtendedStreamReader reader, final ModelNode address, final Namespace expectedNs,
final List<ModelNode> list, final boolean requirePath) throws XMLStreamException {
final Set<String> pathNames = new HashSet<String>();
while (reader.hasNext() && reader.nextTag() != END_ELEMENT) {
final Element element = Element.forName(reader.getLocalName());
requireNamespace(reader, expectedNs);
switch (element) {
case PATH: {
parsePath(reader, address, list, requirePath, pathNames);
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
}
private void parsePath(final XMLExtendedStreamReader reader, final ModelNode address, final List<ModelNode> list,
final boolean requirePath, final Set<String> defined) throws XMLStreamException {
String name = null;
ModelNode path = null;
String relativeTo = null;
final int count = reader.getAttributeCount();
for (int i = 0; i < count; i++) {
final String value = reader.getAttributeValue(i);
if (!isNoNamespaceAttribute(reader, i)) {
throw unexpectedAttribute(reader, i);
} else {
final Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i));
switch (attribute) {
case NAME: {
name = value.trim();
if (RESTRICTED_PATHS.contains(value)) {
throw ControllerLogger.ROOT_LOGGER.reserved(name, reader.getLocation());
}
if (!defined.add(name)) {
throw ControllerLogger.ROOT_LOGGER.alreadyDefined(name, reader.getLocation());
}
break;
}
case PATH: {
path = ParseUtils.parsePossibleExpression(value);
break;
}
case RELATIVE_TO: {
relativeTo = value;
break;
}
default: {
throw unexpectedAttribute(reader, i);
}
}
}
}
if (name == null) {
throw missingRequired(reader, Collections.singleton(Attribute.NAME));
}
if (requirePath && path == null) {
throw missingRequired(reader, Collections.singleton(Attribute.PATH));
}
requireNoContent(reader);
final ModelNode update = new ModelNode();
update.get(OP_ADDR).set(address).add(ModelDescriptionConstants.PATH, name);
update.get(OP).set(ADD);
// update.get(NAME).set(name);
if (path != null)
update.get(PATH).set(path);
if (relativeTo != null)
update.get(RELATIVE_TO).set(relativeTo);
list.add(update);
}
void writePaths(final XMLExtendedStreamWriter writer, final ModelNode node, final boolean namedPath) throws XMLStreamException {
List<Property> paths = node.asPropertyList();
for (Iterator<Property> it = paths.iterator(); it.hasNext(); ) {
ModelNode path = it.next().getValue();
if (!path.isDefined()) {
//The runtime resources for the hardcoded paths don't appear in the model
it.remove();
}
}
if (paths.size() > 0) {
writer.writeStartElement(Element.PATHS.getLocalName());
for (final Property path : paths) {
final ModelNode value = path.getValue();
writer.writeEmptyElement(Element.PATH.getLocalName());
writer.writeAttribute(Attribute.NAME.getLocalName(), path.getName());
if (!namedPath || value.get(PATH).isDefined()) {
writer.writeAttribute(Attribute.PATH.getLocalName(), value.get(PATH).asString());
}
if (value.has(RELATIVE_TO) && value.get(RELATIVE_TO).isDefined()) {
writer.writeAttribute(Attribute.RELATIVE_TO.getLocalName(), value.get(RELATIVE_TO).asString());
}
}
writer.writeEndElement();
}
}
}