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