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 * mcedica 018 */ 019package org.nuxeo.ecm.core.management.storage; 020 021import java.util.ArrayList; 022import java.util.Calendar; 023import java.util.List; 024 025import org.apache.commons.logging.Log; 026import org.apache.commons.logging.LogFactory; 027import org.nuxeo.ecm.core.api.DocumentModel; 028import org.nuxeo.ecm.core.api.DocumentModelList; 029import org.nuxeo.ecm.core.api.DocumentRef; 030import org.nuxeo.ecm.core.api.PathRef; 031import org.nuxeo.ecm.core.management.api.AdministrativeStatus; 032 033/** 034 * Used to control the server administrative status: the status of the server can be passive or active. 035 * 036 * @author Mariana Cedica 037 */ 038public class DocumentModelStatusPersister implements AdministrativeStatusPersister { 039 040 public static final String ADMINISTRATIVE_INFO_CONTAINER = "administrative-infos"; 041 042 public static final String ADMINISTRATIVE_INFO_CONTAINER_DOCUMENT_TYPE = "AdministrativeStatusContainer"; 043 044 public static final String ADMINISTRATIVE_STATUS_DOCUMENT_TYPE = "AdministrativeStatus"; 045 046 public static final String STATUS_PROPERTY = "status:administrative_status"; 047 048 public static final String MESSAGE_PROPERTY = "status:statusMessage"; 049 050 public static final String INSTANCE_PROPERTY = "status:instanceId"; 051 052 public static final String SERVICE_PROPERTY = "status:serviceId"; 053 054 public static final String LOGIN_PROPERTY = "status:userLogin"; 055 056 private static final Log log = LogFactory.getLog(DocumentModelStatusPersister.class); 057 058 private class StatusSaver extends DocumentStoreSessionRunner { 059 060 protected final AdministrativeStatus status; 061 062 private StatusSaver(AdministrativeStatus status) { 063 this.status = status; 064 } 065 066 @Override 067 protected String errorMessage() { 068 return "Cannot save " + status; 069 } 070 071 @Override 072 public void run() { 073 doGetOrCreateDoc(status); 074 session.save(); 075 } 076 077 public AdministrativeStatus getStatus() { 078 return status; 079 } 080 081 protected DocumentModel doGetOrCreateContainer() { 082 083 DocumentRef admRootDocRef = DocumentStoreManager.newPath(ADMINISTRATIVE_INFO_CONTAINER); 084 085 if (!session.exists(admRootDocRef)) { 086 DocumentModel doc = session.createDocumentModel(DocumentStoreManager.newPath().toString(), 087 ADMINISTRATIVE_INFO_CONTAINER, ADMINISTRATIVE_INFO_CONTAINER_DOCUMENT_TYPE); 088 doc.setPropertyValue("dc:title", ADMINISTRATIVE_INFO_CONTAINER); 089 session.createDocument(doc); 090 session.save(); 091 } 092 093 return session.getDocument(admRootDocRef); 094 } 095 096 protected DocumentModel doGetOrCreateDoc(AdministrativeStatus status) { 097 DocumentModel administrativeContainer = doGetOrCreateContainer(); 098 099 DocumentRef statusDocRef = new PathRef(administrativeContainer.getPathAsString() + "/" 100 + getAdministrativeStatusDocName(status)); 101 102 DocumentModel doc; 103 boolean create = false; 104 if (!session.exists(statusDocRef)) { 105 create = true; 106 doc = session.createDocumentModel(administrativeContainer.getPathAsString(), 107 getAdministrativeStatusDocName(status), ADMINISTRATIVE_STATUS_DOCUMENT_TYPE); 108 } else { 109 doc = session.getDocument(statusDocRef); 110 } 111 112 doc.setPropertyValue(LOGIN_PROPERTY, status.getUserLogin()); 113 doc.setPropertyValue(INSTANCE_PROPERTY, status.getInstanceIdentifier()); 114 doc.setPropertyValue(SERVICE_PROPERTY, status.getServiceIdentifier()); 115 doc.setPropertyValue(MESSAGE_PROPERTY, status.getMessage()); 116 doc.setPropertyValue(STATUS_PROPERTY, status.getState()); 117 118 doc.setPropertyValue("dc:title", getAdministrativeStatusDocName(status)); 119 120 if (create) { 121 doc = session.createDocument(doc); 122 } else { 123 doc = session.saveDocument(doc); 124 } 125 session.save(); 126 127 return doc; 128 } 129 130 } 131 132 protected String getAdministrativeStatusDocName(AdministrativeStatus status) { 133 return status.getInstanceIdentifier() + "--" + status.getServiceIdentifier(); 134 } 135 136 public static class StatusFetcher extends DocumentStoreSessionRunner { 137 138 protected final String instanceId; 139 140 protected final String serviceId; 141 142 protected final List<String> allInstanceIds = new ArrayList<>(); 143 144 protected final List<AdministrativeStatus> statuses = new ArrayList<>(); 145 146 public StatusFetcher(String instanceId, String serviceId) { 147 this.instanceId = instanceId; 148 this.serviceId = serviceId; 149 } 150 151 @Override 152 protected String errorMessage() { 153 StringBuilder sb = new StringBuilder(); 154 sb.append("Cannot fetch statuses "); 155 if (instanceId != null) { 156 sb.append(" for ").append(instanceId); 157 } 158 if (serviceId != null) { 159 sb.append(":").append(serviceId); 160 } 161 return sb.toString(); 162 } 163 164 @Override 165 public void run() { 166 StringBuilder sb = new StringBuilder("select * from "); 167 sb.append(ADMINISTRATIVE_STATUS_DOCUMENT_TYPE); 168 169 boolean onlyFetchIds = false; 170 if (instanceId == null) { 171 onlyFetchIds = true; 172 } else { 173 sb.append(" where "); 174 sb.append(INSTANCE_PROPERTY); 175 sb.append("='"); 176 sb.append(instanceId); 177 sb.append("'"); 178 if (serviceId != null) { 179 sb.append(" AND "); 180 sb.append(SERVICE_PROPERTY); 181 sb.append("='"); 182 sb.append(serviceId); 183 sb.append("'"); 184 } 185 } 186 187 DocumentModelList result = session.query(sb.toString()); 188 189 for (DocumentModel doc : result) { 190 if (onlyFetchIds) { 191 String id = (String) doc.getPropertyValue(INSTANCE_PROPERTY); 192 if (!allInstanceIds.contains(id)) { 193 allInstanceIds.add(id); 194 } 195 } else { 196 statuses.add(wrap(doc)); 197 } 198 } 199 } 200 201 protected AdministrativeStatus wrap(DocumentModel doc) { 202 203 String userLogin = (String) doc.getPropertyValue(LOGIN_PROPERTY); 204 String id = (String) doc.getPropertyValue(INSTANCE_PROPERTY); 205 String service = (String) doc.getPropertyValue(SERVICE_PROPERTY); 206 String message = (String) doc.getPropertyValue(MESSAGE_PROPERTY); 207 String state = (String) doc.getPropertyValue(STATUS_PROPERTY); 208 Calendar modified = (Calendar) doc.getPropertyValue("dc:modified"); 209 210 return new AdministrativeStatus(state, message, modified, userLogin, id, service); 211 } 212 } 213 214 @Override 215 public List<String> getAllInstanceIds() { 216 StatusFetcher fetcher = new StatusFetcher(null, null); 217 fetcher.runUnrestricted(); 218 return fetcher.allInstanceIds; 219 } 220 221 @Override 222 public List<AdministrativeStatus> getAllStatuses(String instanceId) { 223 StatusFetcher fetcher = new StatusFetcher(instanceId, null); 224 fetcher.runUnrestricted(); 225 return fetcher.statuses; 226 } 227 228 @Override 229 public AdministrativeStatus getStatus(String instanceId, String serviceIdentifier) { 230 StatusFetcher fetcher = new StatusFetcher(instanceId, serviceIdentifier); 231 fetcher.runUnrestricted(); 232 if (fetcher.statuses.size() == 1) { 233 return fetcher.statuses.get(0); 234 } else { 235 log.warn("Unable to fetch status for service " + serviceIdentifier + " in instance " + instanceId); 236 return null; 237 } 238 } 239 240 @Override 241 public void remove(String instanceId) { 242 throw new UnsupportedOperationException("Not implemented for now"); 243 } 244 245 @Override 246 public AdministrativeStatus saveStatus(AdministrativeStatus status) { 247 StatusSaver saver = new StatusSaver(status); 248 saver.runUnrestricted(); 249 return saver.getStatus(); 250 } 251 252}