PageRenderTime 74ms CodeModel.GetById 40ms app.highlight 29ms RepoModel.GetById 0ms app.codeStats 0ms

/jboss-as-7.1.1.Final/host-controller/src/main/java/org/jboss/as/domain/controller/operations/deployment/DeploymentAddHandler.java

#
Java | 242 lines | 169 code | 21 blank | 52 comment | 25 complexity | 0fa79267bf8db160ad8e83aa5ced69b7 MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0
  1/*
  2 * JBoss, Home of Professional Open Source
  3 * Copyright 2011 Red Hat Inc. and/or its affiliates and other contributors
  4 * as indicated by the @authors tag. All rights reserved.
  5 * See the copyright.txt in the distribution for a
  6 * full listing of individual contributors.
  7 *
  8 * This copyrighted material is made available to anyone wishing to use,
  9 * modify, copy, or redistribute it subject to the terms and conditions
 10 * of the GNU Lesser General Public License, v. 2.1.
 11 * This program is distributed in the hope that it will be useful, but WITHOUT A
 12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 13 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
 14 * You should have received a copy of the GNU Lesser General Public License,
 15 * v.2.1 along with this distribution; if not, write to the Free Software
 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 17 * MA  02110-1301, USA.
 18 */
 19package org.jboss.as.domain.controller.operations.deployment;
 20
 21import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD;
 22import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ARCHIVE;
 23import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.BYTES;
 24import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.CONTENT;
 25import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.HASH;
 26import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.INPUT_STREAM_INDEX;
 27import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.NAME;
 28import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR;
 29import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PATH;
 30import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RELATIVE_TO;
 31import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RUNTIME_NAME;
 32import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.URL;
 33import static org.jboss.as.controller.operations.validation.ChainedParameterValidator.chain;
 34import static org.jboss.as.domain.controller.DomainControllerMessages.MESSAGES;
 35
 36import java.io.ByteArrayInputStream;
 37import java.io.IOException;
 38import java.io.InputStream;
 39import java.net.MalformedURLException;
 40import java.net.URL;
 41import java.util.Arrays;
 42import java.util.List;
 43import java.util.Locale;
 44
 45import org.jboss.as.controller.HashUtil;
 46import org.jboss.as.controller.OperationContext;
 47import org.jboss.as.controller.OperationFailedException;
 48import org.jboss.as.controller.OperationStepHandler;
 49import org.jboss.as.controller.PathAddress;
 50import org.jboss.as.controller.RunningMode;
 51import org.jboss.as.controller.descriptions.DescriptionProvider;
 52import org.jboss.as.controller.descriptions.common.DeploymentDescription;
 53import org.jboss.as.controller.operations.validation.AbstractParameterValidator;
 54import org.jboss.as.controller.operations.validation.ListValidator;
 55import org.jboss.as.controller.operations.validation.ModelTypeValidator;
 56import org.jboss.as.controller.operations.validation.ParametersOfValidator;
 57import org.jboss.as.controller.operations.validation.ParametersValidator;
 58import org.jboss.as.controller.operations.validation.StringLengthValidator;
 59import org.jboss.as.controller.registry.Resource;
 60import org.jboss.as.domain.controller.DomainControllerLogger;
 61import org.jboss.as.protocol.StreamUtils;
 62import org.jboss.as.repository.ContentRepository;
 63import org.jboss.dmr.ModelNode;
 64import org.jboss.dmr.ModelType;
 65
 66/**
 67 * Handles addition of a deployment to the model.
 68 *
 69 * @author Brian Stansberry (c) 2011 Red Hat Inc.
 70 */
 71public class DeploymentAddHandler implements OperationStepHandler, DescriptionProvider {
 72
 73    public static final String OPERATION_NAME = ADD;
 74
 75    private static final List<String> CONTENT_ADDITION_PARAMETERS = Arrays.asList(INPUT_STREAM_INDEX, BYTES, URL);
 76
 77    private final ContentRepository contentRepository;
 78
 79    private final ParametersValidator validator = new ParametersValidator();
 80    private final ParametersValidator unmanagedContentValidator = new ParametersValidator();
 81    private final ParametersValidator managedContentValidator = new ParametersValidator();
 82
 83    /** Constructor for a slave Host Controller */
 84    public DeploymentAddHandler() {
 85        this(null);
 86    }
 87
 88    /**
 89     * Constructor for a master Host Controller
 90     *
 91     * @param contentRepository the master content repository. If {@code null} this handler will function as a slave handler would.
 92     */
 93    public DeploymentAddHandler(final ContentRepository contentRepository) {
 94        this.contentRepository = contentRepository;
 95        this.validator.registerValidator(RUNTIME_NAME, new StringLengthValidator(1, Integer.MAX_VALUE, true, false));
 96        final ParametersValidator contentValidator = new ParametersValidator();
 97        // existing managed content
 98        contentValidator.registerValidator(HASH, new ModelTypeValidator(ModelType.BYTES, true));
 99        // existing unmanaged content
100        contentValidator.registerValidator(ARCHIVE, new ModelTypeValidator(ModelType.BOOLEAN, true));
101        contentValidator.registerValidator(PATH, new StringLengthValidator(1, true));
102        contentValidator.registerValidator(RELATIVE_TO, new ModelTypeValidator(ModelType.STRING, true));
103        // content additions
104        contentValidator.registerValidator(INPUT_STREAM_INDEX, new ModelTypeValidator(ModelType.INT, true));
105        contentValidator.registerValidator(BYTES, new ModelTypeValidator(ModelType.BYTES, true));
106        contentValidator.registerValidator(URL, new StringLengthValidator(1, true));
107        this.validator.registerValidator(CONTENT, chain(new ListValidator(new ParametersOfValidator(contentValidator)),
108                new AbstractParameterValidator() {
109                    @Override
110                    public void validateParameter(String parameterName, ModelNode value) throws OperationFailedException {
111                        validateOnePieceOfContent(value);
112                    }
113                }));
114        this.managedContentValidator.registerValidator(HASH, new ModelTypeValidator(ModelType.BYTES));
115        this.unmanagedContentValidator.registerValidator(ARCHIVE, new ModelTypeValidator(ModelType.BOOLEAN));
116        this.unmanagedContentValidator.registerValidator(PATH, new StringLengthValidator(1));
117    }
118
119    @Override
120    public ModelNode getModelDescription(Locale locale) {
121        return DeploymentDescription.getAddDeploymentOperation(locale, false);
122    }
123
124    /**
125     * {@inheritDoc}
126     */
127    public void execute(OperationContext context, ModelNode operation) throws OperationFailedException {
128        validator.validate(operation);
129        PathAddress address = PathAddress.pathAddress(operation.get(OP_ADDR));
130        String name = address.getLastElement().getValue();
131        String runtimeName = operation.hasDefined(RUNTIME_NAME) ? operation.get(RUNTIME_NAME).asString() : name;
132
133        byte[] hash = null;
134        // clone it, so we can modify it to our own content
135        final ModelNode content = operation.require(CONTENT).clone();
136        // TODO: JBAS-9020: for the moment overlays are not supported, so there is a single content item
137        final ModelNode contentItemNode = content.require(0);
138        if (contentItemNode.hasDefined(HASH)) {
139            managedContentValidator.validate(contentItemNode);
140            hash = contentItemNode.require(HASH).asBytes();
141            // If we are the master, validate that we actually have this content. If we're not the master
142            // we do not need the content until it's added to a server group we care about, so we defer
143            // pulling it until then
144            if (contentRepository != null && !contentRepository.hasContent(hash)) {
145                if (context.isBooting()) {
146                    if (context.getRunningMode() == RunningMode.ADMIN_ONLY) {
147                        // The deployment content is missing, which would be a fatal boot error if we were going to actually
148                        // install services. In ADMIN-ONLY mode we allow it to give the admin a chance to correct the problem
149                        DomainControllerLogger.HOST_CONTROLLER_LOGGER.reportAdminOnlyMissingDeploymentContent(HashUtil.bytesToHexString(hash), name);
150                    } else {
151                        throw createFailureException(MESSAGES.noDeploymentContentWithHashAtBoot(HashUtil.bytesToHexString(hash), name));
152                    }
153                } else {
154                    throw createFailureException(MESSAGES.noDeploymentContentWithHash(HashUtil.bytesToHexString(hash)));
155                }
156            }
157        } else if (hasValidContentAdditionParameterDefined(contentItemNode)) {
158            if (contentRepository == null) {
159                // This is a slave DC. We can't handle this operation; it should have been fixed up on the master DC
160                throw createFailureException(MESSAGES.slaveCannotAcceptUploads());
161            }
162
163            InputStream in = getInputStream(context, contentItemNode);
164            try {
165                try {
166                    hash = contentRepository.addContent(in);
167                } catch (IOException e) {
168                    throw createFailureException(e.toString());
169                }
170
171            } finally {
172                StreamUtils.safeClose(in);
173            }
174            contentItemNode.clear(); // AS7-1029
175            contentItemNode.get(HASH).set(hash);
176        } else {
177            // Unmanaged content, the user is responsible for replication
178            // Just validate the required attributes are present
179            unmanagedContentValidator.validate(contentItemNode);
180        }
181
182        final Resource resource = context.createResource(PathAddress.EMPTY_ADDRESS);
183        final ModelNode subModel = resource.getModel();
184        subModel.get(NAME).set(name);
185        subModel.get(RUNTIME_NAME).set(runtimeName);
186        subModel.get(CONTENT).set(content);
187
188        context.completeStep(OperationContext.RollbackHandler.NOOP_ROLLBACK_HANDLER);
189    }
190
191    private static InputStream getInputStream(OperationContext context, ModelNode operation) throws OperationFailedException {
192        InputStream in = null;
193        String message = "";
194        if (operation.hasDefined(INPUT_STREAM_INDEX)) {
195            int streamIndex = operation.get(INPUT_STREAM_INDEX).asInt();
196            message = MESSAGES.nullStream(streamIndex);
197            in = context.getAttachmentStream(streamIndex);
198        } else if (operation.hasDefined(BYTES)) {
199            message = MESSAGES.invalidByteStream();
200            in = new ByteArrayInputStream(operation.get(BYTES).asBytes());
201        } else if (operation.hasDefined(URL)) {
202            final String urlSpec = operation.get(URL).asString();
203            try {
204                message = MESSAGES.invalidUrlStream();
205                in = new URL(urlSpec).openStream();
206            } catch (MalformedURLException e) {
207                throw createFailureException(message);
208            } catch (IOException e) {
209                throw createFailureException(message);
210            }
211        }
212        if (in == null) {
213            throw createFailureException(message);
214        }
215        return in;
216    }
217
218    /**
219     * Checks to see if a valid deployment parameter has been defined.
220     *
221     * @param operation the operation to check.
222     * @return {@code true} of the parameter is valid, otherwise {@code false}.
223     */
224    private static boolean hasValidContentAdditionParameterDefined(ModelNode operation) {
225        for (String s : CONTENT_ADDITION_PARAMETERS) {
226            if (operation.hasDefined(s)) {
227                return true;
228            }
229        }
230        return false;
231    }
232
233    private static OperationFailedException createFailureException(String msg) {
234        return new OperationFailedException(msg);
235    }
236
237    private static void validateOnePieceOfContent(final ModelNode content) throws OperationFailedException {
238        // TODO: implement overlays
239        if (content.asList().size() != 1)
240            throw createFailureException(MESSAGES.as7431());
241    }
242}