001/* 002 * (C) Copyright 2006-2010 Nuxeo SA (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Thierry Delprat 016 */ 017package org.nuxeo.apidoc.snapshot; 018 019import java.io.IOException; 020import java.io.InputStream; 021import java.io.OutputStream; 022import java.util.ArrayList; 023import java.util.Collections; 024import java.util.Comparator; 025import java.util.HashMap; 026import java.util.List; 027import java.util.Map; 028 029import javax.servlet.http.HttpServletRequest; 030 031import org.apache.commons.logging.Log; 032import org.apache.commons.logging.LogFactory; 033import org.nuxeo.apidoc.api.BundleGroup; 034import org.nuxeo.apidoc.api.BundleInfo; 035import org.nuxeo.apidoc.api.ComponentInfo; 036import org.nuxeo.apidoc.api.ExtensionInfo; 037import org.nuxeo.apidoc.api.ExtensionPointInfo; 038import org.nuxeo.apidoc.api.NuxeoArtifact; 039import org.nuxeo.apidoc.api.OperationInfo; 040import org.nuxeo.apidoc.api.ServiceInfo; 041import org.nuxeo.apidoc.introspection.RuntimeSnapshot; 042import org.nuxeo.apidoc.repository.RepositoryDistributionSnapshot; 043import org.nuxeo.apidoc.repository.SnapshotPersister; 044import org.nuxeo.ecm.automation.OperationException; 045import org.nuxeo.ecm.core.api.CoreSession; 046import org.nuxeo.ecm.core.api.DocumentModel; 047import org.nuxeo.ecm.core.api.DocumentRef; 048import org.nuxeo.ecm.core.api.NuxeoException; 049import org.nuxeo.ecm.core.api.PathRef; 050import org.nuxeo.ecm.core.io.DocumentPipe; 051import org.nuxeo.ecm.core.io.DocumentReader; 052import org.nuxeo.ecm.core.io.DocumentWriter; 053import org.nuxeo.ecm.core.io.impl.DocumentPipeImpl; 054import org.nuxeo.ecm.core.io.impl.plugins.DocumentModelWriter; 055import org.nuxeo.ecm.core.io.impl.plugins.DocumentTreeReader; 056import org.nuxeo.ecm.core.io.impl.plugins.NuxeoArchiveReader; 057import org.nuxeo.ecm.core.io.impl.plugins.NuxeoArchiveWriter; 058import org.nuxeo.runtime.model.DefaultComponent; 059 060public class SnapshotManagerComponent extends DefaultComponent implements SnapshotManager { 061 062 protected DistributionSnapshot runtimeSnapshot; 063 064 public static final String RUNTIME = "current"; 065 066 public static final String RUNTIME_ADM = "adm"; 067 068 protected static final String IMPORT_TMP = "tmpImport"; 069 070 protected static final Log log = LogFactory.getLog(SnapshotManagerComponent.class); 071 072 protected final SnapshotPersister persister = new SnapshotPersister(); 073 074 @Override 075 public DistributionSnapshot getRuntimeSnapshot() { 076 if (runtimeSnapshot == null) { 077 runtimeSnapshot = new RuntimeSnapshot(); 078 } 079 return runtimeSnapshot; 080 } 081 082 @Override 083 public DistributionSnapshot getSnapshot(String key, CoreSession session) { 084 if (key == null || RUNTIME.equals(key) || RUNTIME_ADM.equals(key)) { 085 return getRuntimeSnapshot(); 086 } 087 DistributionSnapshot snap = getPersistentSnapshots(session).get(key); 088 if (snap == null) { 089 DistributionSnapshot rtsnap = getRuntimeSnapshot(); 090 if (rtsnap.getKey().equals(key)) { 091 return rtsnap; 092 } 093 } 094 return snap; 095 } 096 097 @Override 098 public List<DistributionSnapshot> readPersistentSnapshots(CoreSession session) { 099 List<DistributionSnapshot> snaps = RepositoryDistributionSnapshot.readPersistentSnapshots(session); 100 return snaps; 101 } 102 103 @Override 104 public List<DistributionSnapshot> listPersistentSnapshots(CoreSession session) { 105 106 List<DistributionSnapshot> distribs = readPersistentSnapshots(session); 107 108 Collections.sort(distribs, new Comparator<DistributionSnapshot>() { 109 @Override 110 public int compare(DistributionSnapshot dist0, DistributionSnapshot dist1) { 111 if (dist0.getVersion().equals(dist1.getVersion())) { 112 return dist0.getName().compareTo(dist1.getName()); 113 } else { 114 return -dist0.getVersion().compareTo(dist1.getVersion()); 115 } 116 } 117 }); 118 119 return distribs; 120 } 121 122 @Override 123 public Map<String, DistributionSnapshot> getPersistentSnapshots(CoreSession session) { 124 125 Map<String, DistributionSnapshot> persistentSnapshots = new HashMap<String, DistributionSnapshot>(); 126 127 for (DistributionSnapshot snap : readPersistentSnapshots(session)) { 128 persistentSnapshots.put(snap.getKey(), snap); 129 } 130 131 return persistentSnapshots; 132 } 133 134 @Override 135 public List<String> getPersistentSnapshotNames(CoreSession session) { 136 List<String> names = new ArrayList<String>(); 137 names.addAll(getPersistentSnapshots(session).keySet()); 138 return names; 139 } 140 141 @Override 142 public List<DistributionSnapshotDesc> getAvailableDistributions(CoreSession session) { 143 List<DistributionSnapshotDesc> names = new ArrayList<DistributionSnapshotDesc>(); 144 names.addAll(getPersistentSnapshots(session).values()); 145 names.add(0, getRuntimeSnapshot()); 146 return names; 147 } 148 149 @Override 150 public DistributionSnapshot persistRuntimeSnapshot(CoreSession session) { 151 return persistRuntimeSnapshot(session, null); 152 } 153 154 @Override 155 public DistributionSnapshot persistRuntimeSnapshot(CoreSession session, String name) { 156 return persistRuntimeSnapshot(session, name, null); 157 } 158 159 @Override 160 public DistributionSnapshot persistRuntimeSnapshot(CoreSession session, String name, SnapshotFilter filter) { 161 DistributionSnapshot liveSnapshot = getRuntimeSnapshot(); 162 DistributionSnapshot snap = persister.persist(liveSnapshot, session, name, filter); 163 addPersistentSnapshot(snap.getKey(), snap); 164 return snap; 165 } 166 167 @Override 168 public List<String> getAvailableVersions(CoreSession session, NuxeoArtifact nxItem) { 169 List<String> versions = new ArrayList<String>(); 170 171 List<DistributionSnapshot> distribs = new ArrayList<DistributionSnapshot>(); 172 distribs.addAll(getPersistentSnapshots(session).values()); 173 distribs.add(getRuntimeSnapshot()); 174 175 for (DistributionSnapshot snap : distribs) { 176 177 String version = null; 178 if (BundleGroup.TYPE_NAME.equals(nxItem.getArtifactType())) { 179 BundleGroup bg = snap.getBundleGroup(nxItem.getId()); 180 if (bg != null) { 181 version = bg.getVersion(); 182 } 183 } else if (BundleInfo.TYPE_NAME.equals(nxItem.getArtifactType())) { 184 BundleInfo bi = snap.getBundle(nxItem.getId()); 185 if (bi != null) { 186 version = bi.getVersion(); 187 } 188 } else if (ComponentInfo.TYPE_NAME.equals(nxItem.getArtifactType())) { 189 ComponentInfo ci = snap.getComponent(nxItem.getId()); 190 if (ci != null) { 191 version = ci.getVersion(); 192 } 193 } else if (ExtensionInfo.TYPE_NAME.equals(nxItem.getArtifactType())) { 194 ExtensionInfo ei = snap.getContribution(nxItem.getId()); 195 if (ei != null) { 196 version = ei.getVersion(); 197 } 198 } else if (ExtensionPointInfo.TYPE_NAME.equals(nxItem.getArtifactType())) { 199 ExtensionPointInfo epi = snap.getExtensionPoint(nxItem.getId()); 200 if (epi != null) { 201 version = epi.getVersion(); 202 } 203 } else if (ServiceInfo.TYPE_NAME.equals(nxItem.getArtifactType())) { 204 ServiceInfo si = snap.getService(nxItem.getId()); 205 if (si != null) { 206 version = si.getVersion(); 207 } 208 } else if (OperationInfo.TYPE_NAME.equals(nxItem.getArtifactType())) { 209 OperationInfo oi = snap.getOperation(nxItem.getId()); 210 if (oi != null) { 211 version = oi.getVersion(); 212 } 213 } 214 215 if (version != null && !versions.contains(version)) { 216 versions.add(version); 217 } 218 } 219 return versions; 220 } 221 222 @Override 223 public void exportSnapshot(CoreSession session, String key, OutputStream out) throws IOException { 224 225 DistributionSnapshot snap = getSnapshot(key, session); 226 227 if (snap == null) { 228 throw new NuxeoException("Unable to find Snapshot " + key); 229 } 230 231 if (snap.isLive()) { 232 throw new NuxeoException("Can not export a live distribution snapshot : " + key); 233 } 234 235 RepositoryDistributionSnapshot docSnap = (RepositoryDistributionSnapshot) snap; 236 DocumentModel root = docSnap.getDoc(); 237 238 DocumentReader reader = new DocumentTreeReader(session, root); 239 DocumentWriter writer = new NuxeoArchiveWriter(out); 240 DocumentPipe pipe = new DocumentPipeImpl(10); 241 pipe.setReader(reader); 242 pipe.setWriter(writer); 243 pipe.run(); 244 reader.close(); 245 writer.close(); 246 } 247 248 @Override 249 public void importSnapshot(CoreSession session, InputStream is) throws IOException { 250 String importPath = persister.getDistributionRoot(session).getPathAsString(); 251 DocumentReader reader = new NuxeoArchiveReader(is); 252 DocumentWriter writer = new DocumentModelWriter(session, importPath); 253 DocumentPipe pipe = new DocumentPipeImpl(10); 254 pipe.setReader(reader); 255 pipe.setWriter(writer); 256 pipe.run(); 257 reader.close(); 258 writer.close(); 259 } 260 261 @Override 262 public void validateImportedSnapshot(CoreSession session, String name, String version, String pathSegment, 263 String title) { 264 265 DocumentModel container = persister.getDistributionRoot(session); 266 DocumentRef tmpRef = new PathRef(container.getPathAsString(), IMPORT_TMP); 267 268 DocumentModel tmp = null; 269 270 if (session.exists(tmpRef)) { 271 tmp = session.getChild(container.getRef(), IMPORT_TMP); 272 DocumentModel snapDoc = session.getChildren(tmp.getRef()).get(0); 273 snapDoc.setPropertyValue("nxdistribution:name", name); 274 snapDoc.setPropertyValue("nxdistribution:version", version); 275 snapDoc.setPropertyValue("nxdistribution:key", name + "-" + version); 276 snapDoc.setPropertyValue("dc:title", title); 277 snapDoc = session.saveDocument(snapDoc); 278 279 DocumentModel targetContainer = session.getParentDocument(tmp.getRef()); 280 281 session.move(snapDoc.getRef(), targetContainer.getRef(), pathSegment); 282 session.removeDocument(tmp.getRef()); 283 } 284 285 } 286 287 @Override 288 public DocumentModel importTmpSnapshot(CoreSession session, InputStream is) throws IOException { 289 DocumentModel container = persister.getDistributionRoot(session); 290 DocumentRef tmpRef = new PathRef(container.getPathAsString(), IMPORT_TMP); 291 292 DocumentModel tmp = null; 293 294 if (session.exists(tmpRef)) { 295 tmp = session.getChild(container.getRef(), IMPORT_TMP); 296 session.removeChildren(tmp.getRef()); 297 } else { 298 tmp = session.createDocumentModel(container.getPathAsString(), IMPORT_TMP, "Workspace"); 299 tmp.setPropertyValue("dc:title", "tmpImport"); 300 tmp = session.createDocument(tmp); 301 session.save(); 302 } 303 304 DocumentReader reader = new NuxeoArchiveReader(is); 305 DocumentWriter writer = new DocumentModelWriter(session, tmp.getPathAsString()); 306 307 DocumentPipe pipe = new DocumentPipeImpl(10); 308 pipe.setReader(reader); 309 pipe.setWriter(writer); 310 pipe.run(); 311 reader.close(); 312 writer.close(); 313 314 return session.getChildren(tmp.getRef()).get(0); 315 } 316 317 @Override 318 public void initSeamContext(HttpServletRequest request) { 319 ((RuntimeSnapshot) getRuntimeSnapshot()).initSeamComponents(request); 320 } 321 322 @Override 323 public void addPersistentSnapshot(String key, DistributionSnapshot snapshot) { 324 // NOP 325 } 326 327}