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