/* * JBoss, Home of Professional Open Source. * Copyright 2013, 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.model.test; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import org.jboss.as.controller.PathAddress; import org.jboss.as.controller.PathElement; import org.jboss.dmr.ModelNode; /** * * @author <a href="kabir.khan@jboss.com">Kabir Khan</a> */ public class ModelTestOperationValidatorFilter implements Serializable { private static final long serialVersionUID = 1L; private final boolean validateNone; private final List<OperationEntry> entries; private ModelTestOperationValidatorFilter(List<OperationEntry> entries) { this.entries = createStandardEntries(entries); validateNone = false; } private ModelTestOperationValidatorFilter(boolean validateNone) { this.validateNone = validateNone; entries = validateNone ? null : createStandardEntries(null); } private static List<OperationEntry> createStandardEntries(List<OperationEntry> provided) { if (provided == null) { provided = new ArrayList<>(); } // Don't check the private internal op that deregisters itself before we get a chance to validate it OperationEntry oe = new OperationEntry(PathAddress.EMPTY_ADDRESS, "boottime-controller-initializer-step", Action.NOCHECK, null); provided.add(oe); return provided; } public static ModelTestOperationValidatorFilter createValidateNone() { return new ModelTestOperationValidatorFilter(true); } public static ModelTestOperationValidatorFilter createValidateAll() { return new ModelTestOperationValidatorFilter(false); } public static Builder createBuilder() { return new Builder(); } public ModelNode adjustForValidation(ModelNode op) { if (validateNone) { return null; } else if (entries == null) { return op; } //TODO handle composites ModelNode addr = op.get(OP_ADDR); PathAddress address = PathAddress.pathAddress(addr); String name = op.get(OP).asString(); for (OperationEntry entry : entries) { if (nameMatch(name, entry) && addressMatch(address, entry)) { if (entry.action == Action.NOCHECK) { return null; } else if (entry.action == Action.RESOLVE){ op = op.resolve(); } else if (entry.operationFixer != null){ op = entry.operationFixer.fixOperation(op); } } } return op; } private boolean nameMatch(String opName, OperationEntry entry) { if (entry.name.equals("*")) { return true; } return opName.equals(entry.name); } private boolean addressMatch(PathAddress opAddr, OperationEntry entry) { boolean match = entry.address.size() == opAddr.size(); if (match) { for (int i = 0; i < opAddr.size(); i++) { if (!pathElementMatch(opAddr.getElement(i), entry.address.getElement(i))) { match = false; break; } } } return match; } private boolean pathElementMatch(PathElement element, PathElement operationEntryElement) { if (operationEntryElement.getKey().equals("*")) { } else if (!operationEntryElement.getKey().equals(element.getKey())) { return false; } if (operationEntryElement.getValue().equals("*")) { return true; } return operationEntryElement.getValue().equals(element.getValue()); } public static class Builder { List<OperationEntry> entries = new ArrayList<ModelTestOperationValidatorFilter.OperationEntry>(); private Builder() { } public Builder addOperation(PathAddress pathAddress, String name, Action action, OperationFixer operationFixer) { entries.add(new OperationEntry(pathAddress, name, action, operationFixer)); return this; } public ModelTestOperationValidatorFilter build() { return new ModelTestOperationValidatorFilter(entries); } } public static class OperationEntry implements Externalizable { private static final long serialVersionUID = 1L; private volatile PathAddress address; private volatile String name; private volatile Action action; private volatile OperationFixer operationFixer; public OperationEntry(PathAddress address, String name, Action action, OperationFixer operationFixer) { if (operationFixer != null && operationFixer instanceof Serializable == false){ throw new IllegalArgumentException("operationFixer must be serializable"); } this.address = address; this.name = name; this.action = action; this.operationFixer = operationFixer; } public OperationEntry() { } @Override public void writeExternal(ObjectOutput out) throws IOException { out.writeObject(name); out.writeObject(address.toModelNode()); out.writeObject(action); out.writeObject(operationFixer); } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { name = (String)in.readObject(); address = PathAddress.pathAddress((ModelNode)in.readObject()); action = (Action)in.readObject(); operationFixer = (OperationFixer)in.readObject(); } } public static enum Action { NOCHECK, RESOLVE } public static void main(String[] args) { System.out.println(PathAddress.pathAddress(PathElement.pathElement("*", "*"), PathElement.pathElement("x", "*"))); } }