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