001/* 002 * (C) Copyright 2006-2011 Nuxeo SA (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 * Nuxeo - initial API and implementation 018 */ 019 020package org.nuxeo.ecm.core.management.statuses; 021 022import static org.nuxeo.ecm.core.management.api.AdministrativeStatus.ACTIVE; 023import static org.nuxeo.ecm.core.management.api.AdministrativeStatus.PASSIVE; 024 025import java.util.Calendar; 026import java.util.List; 027import java.util.concurrent.Executors; 028import java.util.concurrent.ScheduledExecutorService; 029import java.util.concurrent.ThreadFactory; 030import java.util.concurrent.TimeUnit; 031 032import org.nuxeo.ecm.core.api.security.SecurityConstants; 033import org.nuxeo.ecm.core.management.CoreManagementService; 034import org.nuxeo.ecm.core.management.api.AdministrativeStatus; 035import org.nuxeo.ecm.core.management.api.AdministrativeStatusManager; 036import org.nuxeo.ecm.core.management.api.GlobalAdministrativeStatusManager; 037import org.nuxeo.ecm.core.management.storage.AdministrativeStatusPersister; 038import org.nuxeo.runtime.transaction.TransactionHelper; 039 040/** 041 * Implementation class for the {@link AdministrativeStatusManager} service. For each Nuxeo Instance in the cluster one 042 * instance of this class is created. 043 * 044 * @author tiry 045 */ 046public class AdministrativeStatusManagerImpl implements AdministrativeStatusManager, CoreManagementService { 047 048 protected final AdministrativeStatusPersister persister; 049 050 protected final GlobalAdministrativeStatusManager globalManager; 051 052 protected final String serverInstanceName; 053 054 protected ScheduledExecutorService scheduler; 055 056 protected final Notifier[] notifiers = { new CoreEventNotifier(), new RuntimeEventNotifier() }; 057 058 public AdministrativeStatusManagerImpl(GlobalAdministrativeStatusManager globalManager, 059 AdministrativeStatusPersister persister) { 060 this.globalManager = globalManager; 061 this.persister = persister; 062 serverInstanceName = NuxeoInstanceIdentifierHelper.getServerInstanceName(); 063 } 064 065 public AdministrativeStatusManagerImpl(GlobalAdministrativeStatusManager globalManager, 066 AdministrativeStatusPersister persister, String instanceIdentifier) { 067 this.globalManager = globalManager; 068 this.persister = persister; 069 serverInstanceName = instanceIdentifier; 070 } 071 072 protected String getServerInstanceName() { 073 return serverInstanceName; 074 } 075 076 protected void notifyEvent(String eventName, String instanceIdentifier, String serviceIdentifier) { 077 for (Notifier notifier : notifiers) { 078 notifier.notifyEvent(eventName, instanceIdentifier, serviceIdentifier); 079 } 080 } 081 082 public void onNuxeoServerStartup() { 083 084 List<AdministrativeStatus> savedStatuses = persister.getAllStatuses(serverInstanceName); 085 086 // iterate throw declared services and init them if needed 087 List<AdministrableServiceDescriptor> descs = globalManager.listRegistredServices(); 088 089 for (AdministrableServiceDescriptor desc : descs) { 090 boolean serviceExist = false; 091 for (AdministrativeStatus status : savedStatuses) { 092 if (desc.getId().equals(status.getServiceIdentifier())) { 093 serviceExist = true; 094 break; 095 } 096 } 097 if (!serviceExist) { 098 AdministrativeStatus newStatus = new AdministrativeStatus(desc.getInitialState(), "", 099 Calendar.getInstance(), SecurityConstants.SYSTEM_USERNAME, serverInstanceName, desc.getId()); 100 persister.saveStatus(newStatus); 101 } 102 } 103 104 doNotifyAllStatuses(); 105 106 scheduler = Executors.newScheduledThreadPool(1, new ThreadFactory() { 107 @Override 108 public Thread newThread(Runnable r) { 109 return new Thread(r, "Nuxeo-Administrative-Statuses-Notify-Scheduler"); 110 } 111 }); 112 113 scheduler.scheduleAtFixedRate(new NotifyStatusesHandler(), 5, 5, TimeUnit.MINUTES); 114 } 115 116 protected void doNotifyAllStatuses() { 117 for (AdministrativeStatus status : persister.getAllStatuses(serverInstanceName)) { 118 notifyOnStatus(status); 119 } 120 } 121 122 public class NotifyStatusesHandler implements Runnable { 123 @Override 124 public void run() { 125 TransactionHelper.startTransaction(); 126 boolean notified = false; 127 try { 128 doNotifyAllStatuses(); 129 notified = true; 130 } finally { 131 if (!notified) { 132 TransactionHelper.setTransactionRollbackOnly(); 133 } 134 TransactionHelper.commitOrRollbackTransaction(); 135 } 136 } 137 } 138 139 public void onNuxeoServerShutdown() { 140 if (scheduler == null) { 141 return; 142 } 143 try { 144 scheduler.shutdown(); 145 } finally { 146 scheduler = null; 147 } 148 } 149 150 protected void notifyOnStatus(AdministrativeStatus status) { 151 if (status.isActive()) { 152 notifyEvent(ACTIVATED_EVENT, status.getInstanceIdentifier(), status.getServiceIdentifier()); 153 } else if (status.isPassive()) { 154 notifyEvent(PASSIVATED_EVENT, status.getInstanceIdentifier(), status.getServiceIdentifier()); 155 } 156 } 157 158 @Override 159 public AdministrativeStatus activateNuxeoInstance(String message, String login) { 160 return activate(GLOBAL_INSTANCE_AVAILABILITY, message, login); 161 } 162 163 @Override 164 public AdministrativeStatus deactivateNuxeoInstance(String message, String login) { 165 return deactivate(GLOBAL_INSTANCE_AVAILABILITY, message, login); 166 } 167 168 @Override 169 public AdministrativeStatus getNuxeoInstanceStatus() { 170 return getStatus(GLOBAL_INSTANCE_AVAILABILITY); 171 } 172 173 @Override 174 public AdministrativeStatus setNuxeoInstanceStatus(String state, String message, String login) { 175 return setStatus(GLOBAL_INSTANCE_AVAILABILITY, state, message, login); 176 } 177 178 @Override 179 public AdministrativeStatus activate(String serviceIdentifier, String message, String login) { 180 return setStatus(serviceIdentifier, ACTIVE, message, login); 181 } 182 183 @Override 184 public AdministrativeStatus deactivate(String serviceIdentifier, String message, String login) { 185 return setStatus(serviceIdentifier, PASSIVE, message, login); 186 } 187 188 @Override 189 public AdministrativeStatus setStatus(String serviceIdentifier, String state, String message, String login) { 190 AdministrativeStatus status = new AdministrativeStatus(state, message, Calendar.getInstance(), login, 191 serverInstanceName, serviceIdentifier); 192 status = persister.saveStatus(status); 193 notifyOnStatus(status); 194 return addLabelAndDescription(status); 195 } 196 197 @Override 198 public List<AdministrativeStatus> getAllStatuses() { 199 List<AdministrativeStatus> statuses = persister.getAllStatuses(serverInstanceName); 200 for (AdministrativeStatus status : statuses) { 201 addLabelAndDescription(status); 202 } 203 return statuses; 204 } 205 206 protected AdministrativeStatus addLabelAndDescription(AdministrativeStatus status) { 207 if (status == null) { 208 return null; 209 } 210 String id = status.getServiceIdentifier(); 211 AdministrableServiceDescriptor desc = globalManager.getServiceDescriptor(id); 212 if (desc != null) { 213 status.setLabelAndDescription(desc.getLabel(), desc.getDescription()); 214 } 215 return status; 216 } 217 218 @Override 219 public AdministrativeStatus getStatus(String serviceIdentifier) { 220 AdministrativeStatus status = persister.getStatus(serverInstanceName, serviceIdentifier); 221 addLabelAndDescription(status); 222 return status; 223 } 224 225}