001/*
002 * (C) Copyright 2017 Nuxeo (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *    http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Kevin Leturc <kleturc@nuxeo.com>
018 */
019package org.nuxeo.runtime;
020
021import java.util.ArrayList;
022import java.util.Collections;
023import java.util.List;
024import java.util.logging.Level;
025import java.util.stream.Collectors;
026
027import org.nuxeo.runtime.model.ComponentManager;
028
029/**
030 * Handles runtime messages by taking care of component manager lifecycle in order to work correctly with hot reload.
031 * This is interesting to not store several time the same message in case of hot reload.
032 *
033 * @since 9.10
034 */
035public class RuntimeMessageHandlerImpl implements RuntimeMessageHandler, ComponentManager.Listener {
036
037    protected final List<Message> messages = new ArrayList<>();
038
039    protected ComponentManagerStep step = ComponentManagerStep.ACTIVATING;
040
041    @Override
042    public void addWarning(String message) {
043        messages.add(new Message(step, Level.WARNING, message));
044    }
045
046    @Override
047    public List<String> getWarnings() {
048        return messages.stream().filter(msg -> Level.WARNING.equals(msg.getLevel())).map(Message::getMessage).collect(
049                Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
050    }
051
052    @Override
053    public void addError(String message) {
054        messages.add(new Message(step, Level.SEVERE, message));
055    }
056
057    @Override
058    public List<String> getErrors() {
059        return messages.stream().filter(msg -> Level.SEVERE.equals(msg.getLevel())).map(Message::getMessage).collect(
060                Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
061    }
062
063    @Override
064    public void beforeActivation(ComponentManager mgr) {
065        changeStep(ComponentManagerStep.ACTIVATING);
066    }
067
068    @Override
069    public void beforeStart(ComponentManager mgr, boolean isResume) {
070        changeStep(ComponentManagerStep.STARTING);
071    }
072
073    @Override
074    public void afterStart(ComponentManager mgr, boolean isResume) {
075        changeStep(ComponentManagerStep.RUNNING);
076    }
077
078    @Override
079    public void beforeStop(ComponentManager mgr, boolean isStandby) {
080        changeStep(ComponentManagerStep.STOPPING);
081    }
082
083    @Override
084    public void beforeDeactivation(ComponentManager mgr) {
085        changeStep(ComponentManagerStep.DEACTIVATING);
086    }
087
088    protected void changeStep(ComponentManagerStep step) {
089        messages.removeIf(msg -> step.equals(msg.getStep()));
090        this.step = step;
091    }
092
093    /**
094     * @since 9.10
095     */
096    protected static class Message {
097
098        protected final ComponentManagerStep step;
099
100        protected final Level level;
101
102        protected final String message;
103
104        public Message(ComponentManagerStep step, Level level, String message) {
105            this.step = step;
106            this.level = level;
107            this.message = message;
108        }
109
110        public ComponentManagerStep getStep() {
111            return step;
112        }
113
114        public Level getLevel() {
115            return level;
116        }
117
118        public String getMessage() {
119            return message;
120        }
121
122    }
123
124    /**
125     * @since 9.10
126     */
127    protected enum ComponentManagerStep {
128
129        ACTIVATING,
130
131        STARTING,
132
133        RUNNING,
134
135        STOPPING,
136
137        DEACTIVATING
138
139    }
140
141}