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.repository; 018 019import java.util.ArrayList; 020import java.util.Calendar; 021import java.util.Date; 022import java.util.List; 023 024import org.nuxeo.apidoc.adapters.BaseNuxeoArtifactDocAdapter; 025import org.nuxeo.apidoc.api.BundleGroup; 026import org.nuxeo.apidoc.api.BundleInfo; 027import org.nuxeo.apidoc.api.ComponentInfo; 028import org.nuxeo.apidoc.api.ExtensionInfo; 029import org.nuxeo.apidoc.api.ExtensionPointInfo; 030import org.nuxeo.apidoc.api.OperationInfo; 031import org.nuxeo.apidoc.api.QueryHelper; 032import org.nuxeo.apidoc.api.SeamComponentInfo; 033import org.nuxeo.apidoc.api.ServiceInfo; 034import org.nuxeo.apidoc.documentation.JavaDocHelper; 035import org.nuxeo.apidoc.snapshot.DistributionSnapshot; 036import org.nuxeo.common.utils.Path; 037import org.nuxeo.ecm.core.api.CoreSession; 038import org.nuxeo.ecm.core.api.DocumentModel; 039import org.nuxeo.ecm.core.api.DocumentModelList; 040import org.nuxeo.ecm.core.api.DocumentRef; 041import org.nuxeo.ecm.core.api.PathRef; 042import org.nuxeo.ecm.core.api.PropertyException; 043import org.nuxeo.ecm.core.query.sql.NXQL; 044 045public class RepositoryDistributionSnapshot extends BaseNuxeoArtifactDocAdapter implements DistributionSnapshot { 046 047 protected JavaDocHelper jdocHelper = null; 048 049 public static RepositoryDistributionSnapshot create(DistributionSnapshot distrib, CoreSession session, 050 String containerPath, String label) { 051 DocumentModel doc = session.createDocumentModel(TYPE_NAME); 052 String name = computeDocumentName(distrib.getKey()); 053 if (label != null) { 054 name = computeDocumentName(label); 055 } 056 String targetPath = new Path(containerPath).append(name).toString(); 057 058 boolean exist = false; 059 if (session.exists(new PathRef(targetPath))) { 060 exist = true; 061 doc = session.getDocument(new PathRef(targetPath)); 062 } 063 064 doc.setPathInfo(containerPath, name); 065 if (label == null) { 066 doc.setPropertyValue("dc:title", distrib.getKey()); 067 doc.setPropertyValue(PROP_KEY, distrib.getKey()); 068 doc.setPropertyValue(PROP_NAME, distrib.getName()); 069 doc.setPropertyValue(PROP_VERSION, distrib.getVersion()); 070 } else { 071 doc.setPropertyValue("dc:title", label); 072 doc.setPropertyValue(PROP_KEY, label + "-" + distrib.getVersion()); 073 doc.setPropertyValue(PROP_NAME, label); 074 doc.setPropertyValue(PROP_VERSION, distrib.getVersion()); 075 } 076 077 if (exist) { 078 doc = session.saveDocument(doc); 079 } else { 080 doc = session.createDocument(doc); 081 } 082 return new RepositoryDistributionSnapshot(doc); 083 } 084 085 public static List<DistributionSnapshot> readPersistentSnapshots(CoreSession session) { 086 List<DistributionSnapshot> result = new ArrayList<DistributionSnapshot>(); 087 String query = "SELECT * FROM " + TYPE_NAME + " where ecm:currentLifeCycleState != 'deleted'"; 088 DocumentModelList docs = session.query(query); 089 for (DocumentModel child : docs) { 090 DistributionSnapshot ob = child.getAdapter(DistributionSnapshot.class); 091 if (ob != null) { 092 result.add(ob); 093 } 094 } 095 return result; 096 } 097 098 public RepositoryDistributionSnapshot(DocumentModel doc) { 099 super(doc); 100 } 101 102 protected <T> List<T> getChildren(Class<T> adapter, String docType) { 103 List<T> result = new ArrayList<T>(); 104 String query = QueryHelper.select(docType, doc); 105 DocumentModelList docs = getCoreSession().query(query); 106 for (DocumentModel child : docs) { 107 T ob = child.getAdapter(adapter); 108 if (ob != null) { 109 result.add(ob); 110 } 111 } 112 return result; 113 } 114 115 protected <T> T getChild(Class<T> adapter, String docType, String idField, String id) { 116 String query = QueryHelper.select(docType, doc) + " AND " + idField + " = " + NXQL.escapeString(id); 117 DocumentModelList docs = getCoreSession().query(query); 118 if (docs.isEmpty()) { 119 log.error("Unable to find " + docType + " for id " + id); 120 } else if (docs.size() == 1) { 121 return docs.get(0).getAdapter(adapter); 122 } else { 123 log.error("multiple match for " + docType + " for id " + id); 124 return docs.get(0).getAdapter(adapter); 125 } 126 return null; 127 } 128 129 @Override 130 public BundleInfo getBundle(String id) { 131 return getChild(BundleInfo.class, BundleInfo.TYPE_NAME, BundleInfo.PROP_BUNDLE_ID, id); 132 } 133 134 @Override 135 public BundleGroup getBundleGroup(String groupId) { 136 return getChild(BundleGroup.class, BundleGroup.TYPE_NAME, BundleGroup.PROP_KEY, groupId); 137 } 138 139 protected DocumentModel getBundleContainer() { 140 DocumentRef ref = new PathRef(doc.getPathAsString(), SnapshotPersister.Bundle_Root_NAME); 141 if (getCoreSession().exists(ref)) { 142 return getCoreSession().getDocument(ref); 143 } else { 144 // for compatibility with the previous persistence model 145 return doc; 146 } 147 } 148 149 @Override 150 public List<BundleGroup> getBundleGroups() { 151 List<BundleGroup> grps = new ArrayList<BundleGroup>(); 152 String query = QueryHelper.select(BundleGroup.TYPE_NAME, doc, NXQL.ECM_PARENTID, getBundleContainer().getId()); 153 DocumentModelList docs = getCoreSession().query(query); 154 for (DocumentModel child : docs) { 155 BundleGroup bg = child.getAdapter(BundleGroup.class); 156 if (bg != null) { 157 grps.add(bg); 158 } 159 } 160 return grps; 161 } 162 163 @Override 164 public List<String> getBundleIds() { 165 List<String> ids = new ArrayList<String>(); 166 for (BundleInfo bi : getChildren(BundleInfo.class, BundleInfo.TYPE_NAME)) { 167 ids.add(bi.getId()); 168 } 169 return ids; 170 } 171 172 @Override 173 public ComponentInfo getComponent(String id) { 174 return getChild(ComponentInfo.class, ComponentInfo.TYPE_NAME, ComponentInfo.PROP_COMPONENT_ID, id); 175 } 176 177 @Override 178 public List<String> getComponentIds() { 179 List<String> ids = new ArrayList<String>(); 180 for (ComponentInfo ci : getChildren(ComponentInfo.class, ComponentInfo.TYPE_NAME)) { 181 ids.add(ci.getId()); 182 } 183 return ids; 184 } 185 186 @Override 187 public ExtensionInfo getContribution(String id) { 188 return getChild(ExtensionInfo.class, ExtensionInfo.TYPE_NAME, ExtensionInfo.PROP_CONTRIB_ID, id); 189 } 190 191 @Override 192 public List<String> getContributionIds() { 193 List<String> ids = new ArrayList<String>(); 194 for (ExtensionInfo xi : getChildren(ExtensionInfo.class, ExtensionInfo.TYPE_NAME)) { 195 ids.add(xi.getId()); 196 } 197 return ids; 198 } 199 200 @Override 201 public List<ExtensionInfo> getContributions() { 202 return getChildren(ExtensionInfo.class, ExtensionInfo.TYPE_NAME); 203 } 204 205 @Override 206 public ExtensionPointInfo getExtensionPoint(String id) { 207 return getChild(ExtensionPointInfo.class, ExtensionPointInfo.TYPE_NAME, ExtensionPointInfo.PROP_EP_ID, id); 208 } 209 210 @Override 211 public List<String> getExtensionPointIds() { 212 List<String> ids = new ArrayList<String>(); 213 for (ExtensionPointInfo xpi : getChildren(ExtensionPointInfo.class, ExtensionPointInfo.TYPE_NAME)) { 214 ids.add(xpi.getId()); 215 } 216 return ids; 217 } 218 219 @Override 220 public List<String> getBundleGroupChildren(String groupId) { 221 BundleGroup bg = getChild(BundleGroup.class, BundleGroup.TYPE_NAME, BundleGroup.PROP_KEY, groupId); 222 return bg.getBundleIds(); 223 } 224 225 public List<String> getBundleGroupIds() { 226 List<String> ids = new ArrayList<String>(); 227 for (BundleGroup bg : getChildren(BundleGroup.class, BundleGroup.TYPE_NAME)) { 228 ids.add(bg.getId()); 229 } 230 return ids; 231 } 232 233 @Override 234 public List<String> getServiceIds() { 235 List<String> ids = new ArrayList<String>(); 236 String query = QueryHelper.select(ComponentInfo.TYPE_NAME, doc); 237 DocumentModelList components = getCoreSession().query(query); 238 for (DocumentModel componentDoc : components) { 239 ComponentInfo ci = componentDoc.getAdapter(ComponentInfo.class); 240 if (ci != null) { 241 ids.addAll(ci.getServiceNames()); 242 } 243 } 244 return ids; 245 } 246 247 @Override 248 public String getName() { 249 try { 250 return (String) doc.getPropertyValue(PROP_NAME); 251 } catch (PropertyException e) { 252 log.error("Error while reading nxdistribution:name", e); 253 return "!unknown!"; 254 } 255 } 256 257 @Override 258 public String getVersion() { 259 try { 260 return (String) doc.getPropertyValue(PROP_VERSION); 261 } catch (PropertyException e) { 262 log.error("Error while reading nxdistribution:version", e); 263 return "!unknown!"; 264 } 265 } 266 267 @Override 268 public String getKey() { 269 try { 270 return (String) doc.getPropertyValue(PROP_KEY); 271 } catch (PropertyException e) { 272 log.error("Error while reading nxdistribution:key", e); 273 return "!unknown!"; 274 } 275 } 276 277 @Override 278 public List<Class<?>> getSpi() { 279 return null; 280 } 281 282 @Override 283 public String getId() { 284 return getKey(); 285 } 286 287 @Override 288 public String getArtifactType() { 289 return TYPE_NAME; 290 } 291 292 @Override 293 public ServiceInfo getService(String id) { 294 String query = QueryHelper.select(ServiceInfo.TYPE_NAME, getDoc()) + " AND " + ServiceInfo.PROP_CLASS_NAME 295 + " = " + NXQL.escapeString(id); 296 DocumentModelList docs = getCoreSession().query(query); 297 if (docs.size() == 1) { 298 return docs.get(0).getAdapter(ServiceInfo.class); 299 } else { 300 log.error("Multiple services found"); 301 return null; 302 } 303 } 304 305 @Override 306 public List<String> getJavaComponentIds() { 307 List<String> ids = new ArrayList<String>(); 308 for (ComponentInfo ci : getChildren(ComponentInfo.class, ComponentInfo.TYPE_NAME)) { 309 if (!ci.isXmlPureComponent()) { 310 ids.add(ci.getId()); 311 } 312 } 313 return ids; 314 } 315 316 @Override 317 public List<String> getXmlComponentIds() { 318 List<String> ids = new ArrayList<String>(); 319 for (ComponentInfo ci : getChildren(ComponentInfo.class, ComponentInfo.TYPE_NAME)) { 320 if (ci.isXmlPureComponent()) { 321 ids.add(ci.getId()); 322 } 323 } 324 return ids; 325 } 326 327 @Override 328 public Date getCreationDate() { 329 try { 330 Calendar cal = (Calendar) getDoc().getPropertyValue("dc:created"); 331 return cal == null ? null : cal.getTime(); 332 } catch (PropertyException e) { 333 return null; 334 } 335 } 336 337 @Override 338 public boolean isLive() { 339 return false; 340 } 341 342 @Override 343 public SeamComponentInfo getSeamComponent(String id) { 344 String name = id.replace("seam:", ""); 345 String query = QueryHelper.select(SeamComponentInfo.TYPE_NAME, getDoc()) + " AND " 346 + SeamComponentInfo.PROP_COMPONENT_NAME + " = " + NXQL.escapeString(name); 347 DocumentModelList docs = getCoreSession().query(query); 348 return docs.isEmpty() ? null : docs.get(0).getAdapter(SeamComponentInfo.class); 349 } 350 351 @Override 352 public List<String> getSeamComponentIds() { 353 List<String> result = new ArrayList<String>(); 354 String query = QueryHelper.select(SeamComponentInfo.TYPE_NAME, getDoc()); 355 DocumentModelList docs = getCoreSession().query(query); 356 for (DocumentModel doc : docs) { 357 result.add(doc.getAdapter(SeamComponentInfo.class).getId()); 358 } 359 return result; 360 } 361 362 @Override 363 public List<SeamComponentInfo> getSeamComponents() { 364 List<SeamComponentInfo> result = new ArrayList<SeamComponentInfo>(); 365 String query = QueryHelper.select(SeamComponentInfo.TYPE_NAME, getDoc()); 366 DocumentModelList docs = getCoreSession().query(query); 367 for (DocumentModel doc : docs) { 368 result.add(doc.getAdapter(SeamComponentInfo.class)); 369 } 370 return result; 371 } 372 373 @Override 374 public boolean containsSeamComponents() { 375 return getSeamComponentIds().size() > 0; 376 } 377 378 @Override 379 public OperationInfo getOperation(String id) { 380 if (id.startsWith(OperationInfo.ARTIFACT_PREFIX)) { 381 id = id.substring(OperationInfo.ARTIFACT_PREFIX.length()); 382 } 383 String query = QueryHelper.select(OperationInfo.TYPE_NAME, getDoc()) + " AND " + OperationInfo.PROP_NAME + " = " 384 + NXQL.escapeString(id); 385 DocumentModelList docs = getCoreSession().query(query); 386 return docs.isEmpty() ? null : docs.get(0).getAdapter(OperationInfo.class); 387 } 388 389 @Override 390 public List<OperationInfo> getOperations() { 391 List<OperationInfo> result = new ArrayList<OperationInfo>(); 392 String query = QueryHelper.select(OperationInfo.TYPE_NAME, getDoc()); 393 DocumentModelList docs = getCoreSession().query(query); 394 for (DocumentModel doc : docs) { 395 result.add(doc.getAdapter(OperationInfo.class)); 396 } 397 // TODO sort 398 return result; 399 } 400 401 @Override 402 public JavaDocHelper getJavaDocHelper() { 403 if (jdocHelper == null) { 404 jdocHelper = JavaDocHelper.getHelper(getName(), getVersion()); 405 } 406 return jdocHelper; 407 } 408 409 @Override 410 public void cleanPreviousArtifacts() { 411 String query = QueryHelper.select("Document", getDoc()); 412 List<DocumentRef> refs = new ArrayList<>(); 413 DocumentModelList docs = getCoreSession().query(query); 414 for (DocumentModel doc : docs) { 415 refs.add(doc.getRef()); 416 } 417 getCoreSession().removeDocuments(refs.toArray(new DocumentRef[refs.size()])); 418 } 419}