/* * JBoss, Home of Professional Open Source. * Copyright 2012, 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.deploymentoverlay; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.CONTENT; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.HASH; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.UUID; import org.jboss.as.controller.AttributeDefinition; import org.jboss.as.controller.ModelVersion; import org.jboss.as.controller.ObjectTypeAttributeDefinition; import org.jboss.as.controller.OperationContext; import org.jboss.as.controller.OperationFailedException; import org.jboss.as.controller.OperationStepHandler; import org.jboss.as.controller.ParameterCorrector; import org.jboss.as.controller.PathAddress; import org.jboss.as.controller.PathElement; import org.jboss.as.controller.SimpleAttributeDefinition; import org.jboss.as.controller.SimpleAttributeDefinitionBuilder; import org.jboss.as.controller.SimpleOperationDefinition; import org.jboss.as.controller.SimpleOperationDefinitionBuilder; import org.jboss.as.controller.SimpleResourceDefinition; import org.jboss.as.controller.descriptions.ModelDescriptionConstants; import org.jboss.as.controller.descriptions.common.ControllerResolver; import org.jboss.as.controller.operations.validation.BytesValidator; import org.jboss.as.controller.operations.validation.MinMaxValidator; import org.jboss.as.controller.operations.validation.ModelTypeValidator; import org.jboss.as.controller.operations.validation.StringLengthValidator; import org.jboss.as.controller.registry.ManagementResourceRegistration; import org.jboss.as.controller.registry.Resource; import org.jboss.as.repository.ContentRepository; import org.jboss.as.repository.DeploymentFileRepository; import org.jboss.as.repository.ExplodedContentException; import org.jboss.as.repository.TypedInputStream; import org.jboss.dmr.ModelNode; import org.jboss.dmr.ModelType; /** * @author Stuart Douglas */ public class DeploymentOverlayContentDefinition extends SimpleResourceDefinition { public static final ObjectTypeAttributeDefinition CONTENT_PARAMETER = new ObjectTypeAttributeDefinition.Builder(ModelDescriptionConstants.CONTENT, new SimpleAttributeDefinitionBuilder(ModelDescriptionConstants.INPUT_STREAM_INDEX, ModelType.INT, true) .setValidator(new StringLengthValidator(0, true)) .build(), new SimpleAttributeDefinitionBuilder(ModelDescriptionConstants.HASH, ModelType.BYTES, true) .setValidator(new HashValidator(true)) .build(), new SimpleAttributeDefinitionBuilder(ModelDescriptionConstants.BYTES, ModelType.BYTES, true) .setValidator(new BytesValidator(1, Integer.MAX_VALUE, true)) .build(), new SimpleAttributeDefinitionBuilder(ModelDescriptionConstants.URL, ModelType.STRING, true) .setValidator(new StringLengthValidator(1, true)) .build()) .setCorrector(ContentCorrector.INSTANCE) .build(); public static final SimpleAttributeDefinition CONTENT_ATTRIBUTE = new SimpleAttributeDefinitionBuilder(ModelDescriptionConstants.CONTENT, ModelType.BYTES, true) .setValidator(new HashValidator(true)) .build(); public static final SimpleAttributeDefinition STREAM_ATTRIBUTE = SimpleAttributeDefinitionBuilder.create("stream", ModelType.STRING, true) .setStorageRuntime() .setRuntimeServiceNotRequired() .build(); private final ContentRepository contentRepository; private final OperationStepHandler addHandler; private static final SimpleOperationDefinition READ_CONTENT_OP_DEFINITION = new SimpleOperationDefinitionBuilder(ModelDescriptionConstants.READ_CONTENT, ControllerResolver.getResolver(ModelDescriptionConstants.DEPLOYMENT_OVERLAY, ModelDescriptionConstants.CONTENT)) .setDeprecated(ModelVersion.create(5, 0, 0)) .build(); private static final SimpleOperationDefinition ADD_OP_DEFINITION = new SimpleOperationDefinitionBuilder(ModelDescriptionConstants.ADD, ControllerResolver.getResolver(ModelDescriptionConstants.DEPLOYMENT_OVERLAY)) .setParameters(CONTENT_PARAMETER) .build(); private static final AttributeDefinition[] ATTRIBUTES = {CONTENT_ATTRIBUTE}; public static AttributeDefinition[] attributes() { return ATTRIBUTES.clone(); } public DeploymentOverlayContentDefinition(final ContentRepository contentRepository, final DeploymentFileRepository remoteRepository) { super(DeploymentOverlayModel.CONTENT_PATH, ControllerResolver.getResolver(ModelDescriptionConstants.DEPLOYMENT_OVERLAY, ModelDescriptionConstants.CONTENT), null, new DeploymentOverlayContentRemove(contentRepository)); this.contentRepository = contentRepository; addHandler = new DeploymentOverlayContentAdd(contentRepository, remoteRepository); } @Override public void registerAttributes(final ManagementResourceRegistration resourceRegistration) { super.registerAttributes(resourceRegistration); for (AttributeDefinition attr : ATTRIBUTES) { resourceRegistration.registerReadOnlyAttribute(attr, null); } resourceRegistration.registerReadOnlyAttribute(STREAM_ATTRIBUTE, new DeploymentOverlayReadContentHandler(contentRepository)); } @Override public void registerOperations(final ManagementResourceRegistration resourceRegistration) { super.registerOperations(resourceRegistration); resourceRegistration.registerOperationHandler(READ_CONTENT_OP_DEFINITION, new ReadContentHandler(contentRepository)); resourceRegistration.registerOperationHandler(ADD_OP_DEFINITION, addHandler); } private static class HashValidator extends ModelTypeValidator implements MinMaxValidator { public HashValidator(boolean nillable) { super(ModelType.BYTES, nillable); } @Override public Long getMin() { return 20L; } @Override public Long getMax() { return 20L; } } private static class ContentCorrector implements ParameterCorrector { static final ParameterCorrector INSTANCE = new ContentCorrector(); @Override public ModelNode correct(ModelNode newValue, ModelNode currentValue) { if (newValue.isDefined() && newValue.getType() == ModelType.BYTES) { //The generated add from the model sync does not wrap the hash, adjust that here ModelNode corrected = new ModelNode(); corrected.get(HASH).set(newValue); return corrected; } return newValue; } } private static class DeploymentOverlayReadContentHandler implements OperationStepHandler { protected final ContentRepository contentRepository; public DeploymentOverlayReadContentHandler(final ContentRepository contentRepository) { this.contentRepository = contentRepository; } @Override public void execute(final OperationContext context, final ModelNode operation) throws OperationFailedException { final PathAddress address = PathAddress.pathAddress(operation.get(OP_ADDR)); Resource resource = context.getOriginalRootResource(); for (final PathElement element : address) { resource = resource.getChild(element); } byte[] contentHash = resource.getModel().get(CONTENT).asBytes(); try { TypedInputStream inputStream = contentRepository.readContent(contentHash, ""); String uuid = context.attachResultStream(inputStream.getContentType(), inputStream); context.getResult().get(UUID).set(uuid); } catch (ExplodedContentException ex) { throw new RuntimeException(ex.getMessage(), ex); } } } }