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