/*
* (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Contributors:
* mcedica
*/
package org.nuxeo.ecm.core.management.storage;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.nuxeo.ecm.core.api.DocumentModelList;
import org.nuxeo.ecm.core.api.DocumentRef;
import org.nuxeo.ecm.core.api.PathRef;
import org.nuxeo.ecm.core.management.api.AdministrativeStatus;
import org.nuxeo.runtime.api.Framework;
import org.nuxeo.runtime.osgi.OSGiRuntimeService;
/**
* Used to control the server administrative status: the status of the server can be passive or active.
*
* @author Mariana Cedica
*/
public class DocumentModelStatusPersister implements AdministrativeStatusPersister {
public static final String ADMINISTRATIVE_INFO_CONTAINER = "administrative-infos";
public static final String ADMINISTRATIVE_INFO_CONTAINER_DOCUMENT_TYPE = "AdministrativeStatusContainer";
public static final String ADMINISTRATIVE_STATUS_DOCUMENT_TYPE = "AdministrativeStatus";
public static final String STATUS_PROPERTY = "status:administrative_status";
public static final String MESSAGE_PROPERTY = "status:statusMessage";
public static final String INSTANCE_PROPERTY = "status:instanceId";
public static final String SERVICE_PROPERTY = "status:serviceId";
public static final String LOGIN_PROPERTY = "status:userLogin";
private static final Log log = LogFactory.getLog(DocumentModelStatusPersister.class);
private class StatusSaver extends DocumentStoreSessionRunner {
protected final AdministrativeStatus status;
private StatusSaver(AdministrativeStatus status) {
this.status = status;
}
@Override
protected String errorMessage() {
return "Cannot save " + status;
}
@Override
public void run() {
doGetOrCreateDoc(status);
session.save();
}
public AdministrativeStatus getStatus() {
return status;
}
protected DocumentModel doGetOrCreateContainer() {
DocumentRef admRootDocRef = DocumentStoreManager.newPath(ADMINISTRATIVE_INFO_CONTAINER);
if (!session.exists(admRootDocRef)) {
DocumentModel doc = session.createDocumentModel(DocumentStoreManager.newPath().toString(),
ADMINISTRATIVE_INFO_CONTAINER, ADMINISTRATIVE_INFO_CONTAINER_DOCUMENT_TYPE);
doc.setPropertyValue("dc:title", ADMINISTRATIVE_INFO_CONTAINER);
doc = session.createDocument(doc);
session.save();
}
return session.getDocument(admRootDocRef);
}
protected DocumentModel doGetOrCreateDoc(AdministrativeStatus status) {
DocumentModel administrativeContainer = doGetOrCreateContainer();
DocumentRef statusDocRef = new PathRef(administrativeContainer.getPathAsString() + "/"
+ getAdministrativeStatusDocName(status));
DocumentModel doc;
boolean create = false;
if (!session.exists(statusDocRef)) {
create = true;
doc = session.createDocumentModel(administrativeContainer.getPathAsString(),
getAdministrativeStatusDocName(status), ADMINISTRATIVE_STATUS_DOCUMENT_TYPE);
} else {
doc = session.getDocument(statusDocRef);
}
doc.setPropertyValue(LOGIN_PROPERTY, status.getUserLogin());
doc.setPropertyValue(INSTANCE_PROPERTY, status.getInstanceIdentifier());
doc.setPropertyValue(SERVICE_PROPERTY, status.getServiceIdentifier());
doc.setPropertyValue(MESSAGE_PROPERTY, status.getMessage());
doc.setPropertyValue(STATUS_PROPERTY, status.getState());
doc.setPropertyValue("dc:title", getAdministrativeStatusDocName(status));
if (create) {
doc = session.createDocument(doc);
} else {
doc = session.saveDocument(doc);
}
session.save();
return doc;
}
}
protected String getAdministrativeStatusDocName(AdministrativeStatus status) {
return status.getInstanceIdentifier() + "--" + status.getServiceIdentifier();
}
public static class StatusFetcher extends DocumentStoreSessionRunner {
protected final String instanceId;
protected final String serviceId;
protected final List<String> allInstanceIds = new ArrayList<String>();
protected final List<AdministrativeStatus> statuses = new ArrayList<AdministrativeStatus>();
public StatusFetcher(String instanceId, String serviceId) {
this.instanceId = instanceId;
this.serviceId = serviceId;
}
@Override
protected String errorMessage() {
StringBuilder sb = new StringBuilder();
sb.append("Cannot fetch statuses ");
if (instanceId != null) {
sb.append(" for ").append(instanceId);
}
if (serviceId != null) {
sb.append(":").append(serviceId);
}
return sb.toString();
}
@Override
public void run() {
StringBuilder sb = new StringBuilder("select * from ");
sb.append(ADMINISTRATIVE_STATUS_DOCUMENT_TYPE);
boolean onlyFetchIds = false;
if (instanceId == null) {
onlyFetchIds = true;
} else {
sb.append(" where ");
sb.append(INSTANCE_PROPERTY);
sb.append("='");
sb.append(instanceId);
sb.append("'");
if (serviceId != null) {
sb.append(" AND ");
sb.append(SERVICE_PROPERTY);
sb.append("='");
sb.append(serviceId);
sb.append("'");
}
}
DocumentModelList result = session.query(sb.toString());
for (DocumentModel doc : result) {
if (onlyFetchIds) {
String id = (String) doc.getPropertyValue(INSTANCE_PROPERTY);
if (!allInstanceIds.contains(id)) {
allInstanceIds.add(id);
}
} else {
statuses.add(wrap(doc));
}
}
}
protected AdministrativeStatus wrap(DocumentModel doc) {
String userLogin = (String) doc.getPropertyValue(LOGIN_PROPERTY);
String id = (String) doc.getPropertyValue(INSTANCE_PROPERTY);
String service = (String) doc.getPropertyValue(SERVICE_PROPERTY);
String message = (String) doc.getPropertyValue(MESSAGE_PROPERTY);
String state = (String) doc.getPropertyValue(STATUS_PROPERTY);
Calendar modified = (Calendar) doc.getPropertyValue("dc:modified");
return new AdministrativeStatus(state, message, modified, userLogin, id, service);
}
}
@Override
public List<String> getAllInstanceIds() {
StatusFetcher fetcher = new StatusFetcher(null, null);
fetcher.runUnrestricted();
return fetcher.allInstanceIds;
}
@Override
public List<AdministrativeStatus> getAllStatuses(String instanceId) {
StatusFetcher fetcher = new StatusFetcher(instanceId, null);
fetcher.runUnrestricted();
return fetcher.statuses;
}
@Override
public AdministrativeStatus getStatus(String instanceId, String serviceIdentifier) {
StatusFetcher fetcher = new StatusFetcher(instanceId, serviceIdentifier);
fetcher.runUnrestricted();
if (fetcher.statuses.size() == 1) {
return fetcher.statuses.get(0);
} else {
log.warn("Unable to fetch status for service " + serviceIdentifier + " in instance " + instanceId);
return null;
}
}
@Override
public void remove(String instanceId) {
throw new UnsupportedOperationException("Not implemented for now");
}
@Override
public AdministrativeStatus saveStatus(AdministrativeStatus status) {
StatusSaver saver = new StatusSaver(status);
saver.runUnrestricted();
return saver.getStatus();
}
}