001/* 002 * Copyright (c) 2006-2015 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the Eclipse Public License v1.0 006 * which accompanies this distribution, and is available at 007 * http://www.eclipse.org/legal/epl-v10.html 008 * 009 * Contributors: 010 * Florent Guillaume 011 */ 012package org.nuxeo.ecm.core.opencmis.impl.server; 013 014import static org.apache.chemistry.opencmis.commons.BasicPermissions.ALL; 015import static org.apache.chemistry.opencmis.commons.BasicPermissions.READ; 016import static org.apache.chemistry.opencmis.commons.BasicPermissions.WRITE; 017import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_ADD_POLICY_OBJECT; 018import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_ADD_POLICY_POLICY; 019import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_ADD_TO_FOLDER_FOLDER; 020import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_ADD_TO_FOLDER_OBJECT; 021import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_APPLY_ACL_OBJECT; 022import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_CANCEL_CHECKOUT_DOCUMENT; 023import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_CHECKIN_DOCUMENT; 024import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_CHECKOUT_DOCUMENT; 025import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_CREATE_DOCUMENT_FOLDER; 026import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_CREATE_FOLDER_FOLDER; 027import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_CREATE_RELATIONSHIP_SOURCE; 028import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_CREATE_RELATIONSHIP_TARGET; 029import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_DELETE_CONTENT_DOCUMENT; 030import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_DELETE_OBJECT; 031import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_DELETE_TREE_FOLDER; 032import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_GET_ACL_OBJECT; 033import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_GET_ALL_VERSIONS_VERSION_SERIES; 034import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_GET_APPLIED_POLICIES_OBJECT; 035import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_GET_CHILDREN_FOLDER; 036import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_GET_DESCENDENTS_FOLDER; 037import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_GET_FOLDER_PARENT_OBJECT; 038import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_GET_OBJECT_RELATIONSHIPS_OBJECT; 039import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_GET_PARENTS_FOLDER; 040import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_GET_PROPERTIES_OBJECT; 041import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_MOVE_OBJECT; 042import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_MOVE_SOURCE; 043import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_MOVE_TARGET; 044import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_REMOVE_FROM_FOLDER_FOLDER; 045import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_REMOVE_FROM_FOLDER_OBJECT; 046import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_REMOVE_POLICY_OBJECT; 047import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_REMOVE_POLICY_POLICY; 048import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_SET_CONTENT_DOCUMENT; 049import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_UPDATE_PROPERTIES_OBJECT; 050import static org.apache.chemistry.opencmis.commons.data.PermissionMapping.CAN_VIEW_CONTENT_OBJECT; 051 052import java.lang.reflect.Field; 053import java.math.BigInteger; 054import java.util.ArrayList; 055import java.util.Arrays; 056import java.util.Collections; 057import java.util.HashMap; 058import java.util.HashSet; 059import java.util.LinkedList; 060import java.util.List; 061import java.util.Map; 062import java.util.Map.Entry; 063import java.util.Set; 064 065import javax.servlet.http.HttpServletRequest; 066 067import org.apache.chemistry.opencmis.commons.data.ExtensionFeature; 068import org.apache.chemistry.opencmis.commons.data.PermissionMapping; 069import org.apache.chemistry.opencmis.commons.data.RepositoryInfo; 070import org.apache.chemistry.opencmis.commons.definitions.PermissionDefinition; 071import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition; 072import org.apache.chemistry.opencmis.commons.definitions.TypeDefinitionContainer; 073import org.apache.chemistry.opencmis.commons.definitions.TypeDefinitionList; 074import org.apache.chemistry.opencmis.commons.enums.AclPropagation; 075import org.apache.chemistry.opencmis.commons.enums.BaseTypeId; 076import org.apache.chemistry.opencmis.commons.enums.CapabilityAcl; 077import org.apache.chemistry.opencmis.commons.enums.CapabilityChanges; 078import org.apache.chemistry.opencmis.commons.enums.CapabilityContentStreamUpdates; 079import org.apache.chemistry.opencmis.commons.enums.CapabilityJoin; 080import org.apache.chemistry.opencmis.commons.enums.CapabilityQuery; 081import org.apache.chemistry.opencmis.commons.enums.CapabilityRenditions; 082import org.apache.chemistry.opencmis.commons.enums.CmisVersion; 083import org.apache.chemistry.opencmis.commons.enums.SupportedPermissions; 084import org.apache.chemistry.opencmis.commons.impl.dataobjects.AclCapabilitiesDataImpl; 085import org.apache.chemistry.opencmis.commons.impl.dataobjects.CreatablePropertyTypesImpl; 086import org.apache.chemistry.opencmis.commons.impl.dataobjects.NewTypeSettableAttributesImpl; 087import org.apache.chemistry.opencmis.commons.impl.dataobjects.PermissionDefinitionDataImpl; 088import org.apache.chemistry.opencmis.commons.impl.dataobjects.PermissionMappingDataImpl; 089import org.apache.chemistry.opencmis.commons.impl.dataobjects.RepositoryCapabilitiesImpl; 090import org.apache.chemistry.opencmis.commons.impl.dataobjects.RepositoryInfoImpl; 091import org.apache.chemistry.opencmis.commons.server.CallContext; 092 093import org.nuxeo.common.Environment; 094import org.nuxeo.ecm.core.api.security.PermissionProvider; 095import org.nuxeo.ecm.core.api.security.SecurityConstants; 096import org.nuxeo.ecm.core.opencmis.impl.util.TypeManagerImpl; 097import org.nuxeo.ecm.core.schema.DocumentType; 098import org.nuxeo.ecm.core.schema.SchemaManager; 099import org.nuxeo.ecm.core.schema.types.CompositeType; 100import org.nuxeo.ecm.core.security.DefaultPermissionProvider; 101import org.nuxeo.ecm.core.security.PermissionVisibilityDescriptor; 102import org.nuxeo.runtime.api.Framework; 103 104/** 105 * Information about a Nuxeo repository. 106 */ 107public class NuxeoRepository { 108 109 /** 110 * @deprecated Since 7.10. Use {@link Environment#DISTRIBUTION_VERSION} 111 */ 112 @Deprecated 113 public static final String NUXEO_VERSION_PROP = Environment.DISTRIBUTION_VERSION; 114 115 public static final String NUXEO_URL_PROP = "nuxeo.url"; 116 117 public static final String SUPPORTS_JOINS_PROP = "org.nuxeo.cmis.joins"; 118 119 public static final String ELASTICSEARCH_PROP = "org.nuxeo.cmis.elasticsearch"; 120 121 private static final String NUXEO_CONTEXT_PATH_PROP = "org.nuxeo.ecm.contextPath"; 122 123 private static final String NUXEO_CONTEXT_PATH_DEFAULT = "/nuxeo"; 124 125 private static final String X_FORWARDED_HOST = "x-forwarded-host"; 126 127 private static final String NUXEO_VH_HEADER = "nuxeo-virtual-host"; 128 129 private static final String VH_PARAM = "nuxeo.virtual.host"; 130 131 public static final String NUXEO_READ_REMOVE = "ReadRemove"; 132 133 protected final String repositoryId; 134 135 protected final String rootFolderId; 136 137 protected boolean supportsJoins; 138 139 protected boolean useElasticsearch; 140 141 protected TypeManagerImpl typeManager; 142 143 protected CmisVersion cmisVersion; 144 145 public NuxeoRepository(String repositoryId, String rootFolderId) { 146 this.repositoryId = repositoryId; 147 this.rootFolderId = rootFolderId; 148 if (Framework.isBooleanPropertyTrue(SUPPORTS_JOINS_PROP)) { 149 setSupportsJoins(true); 150 } 151 if (Framework.isBooleanPropertyTrue(ELASTICSEARCH_PROP)) { 152 setUseElasticsearch(true); 153 } 154 } 155 156 public void setSupportsJoins(boolean supportsJoins) { 157 this.supportsJoins = supportsJoins; 158 } 159 160 public boolean supportsJoins() { 161 return supportsJoins; 162 } 163 164 public void setUseElasticsearch(boolean useElasticsearch) { 165 this.useElasticsearch = useElasticsearch; 166 } 167 168 public boolean useElasticsearch() { 169 return useElasticsearch; 170 } 171 172 public String getId() { 173 return repositoryId; 174 } 175 176 // no need to have it synchronized 177 public TypeManagerImpl getTypeManager() { 178 if (typeManager == null) { 179 typeManager = initializeTypes(); 180 } 181 return typeManager; 182 } 183 184 protected TypeManagerImpl initializeTypes() { 185 SchemaManager schemaManager = Framework.getService(SchemaManager.class); 186 // scan the types to find super/inherited relationships 187 Map<String, List<String>> typesChildren = new HashMap<>(); 188 for (DocumentType dt : schemaManager.getDocumentTypes()) { 189 org.nuxeo.ecm.core.schema.types.Type st = dt.getSuperType(); 190 if (st == null) { 191 continue; 192 } 193 String name = st.getName(); 194 List<String> siblings = typesChildren.get(name); 195 if (siblings == null) { 196 siblings = new LinkedList<>(); 197 typesChildren.put(name, siblings); 198 } 199 siblings.add(dt.getName()); 200 } 201 // convert the transitive closure for Folder and Document subtypes 202 Set<String> done = new HashSet<>(); 203 TypeManagerImpl typeManager = new TypeManagerImpl(); 204 typeManager.addTypeDefinition(NuxeoTypeHelper.constructCmisBase(BaseTypeId.CMIS_DOCUMENT, schemaManager, cmisVersion)); 205 typeManager.addTypeDefinition(NuxeoTypeHelper.constructCmisBase(BaseTypeId.CMIS_FOLDER, schemaManager, cmisVersion)); 206 typeManager.addTypeDefinition(NuxeoTypeHelper.constructCmisBase(BaseTypeId.CMIS_RELATIONSHIP, schemaManager, cmisVersion)); 207 if (cmisVersion != CmisVersion.CMIS_1_0) { 208 typeManager.addTypeDefinition(NuxeoTypeHelper.constructCmisBase(BaseTypeId.CMIS_SECONDARY, schemaManager, cmisVersion)); 209 } 210 addTypesRecursively(typeManager, NuxeoTypeHelper.NUXEO_DOCUMENT, typesChildren, done, schemaManager); 211 addTypesRecursively(typeManager, NuxeoTypeHelper.NUXEO_FOLDER, typesChildren, done, schemaManager); 212 addTypesRecursively(typeManager, NuxeoTypeHelper.NUXEO_RELATION, typesChildren, done, schemaManager); 213 if (cmisVersion != CmisVersion.CMIS_1_0) { 214 addSecondaryTypes(typeManager, schemaManager); 215 } 216 return typeManager; 217 } 218 219 protected void addTypesRecursively(TypeManagerImpl typeManager, String name, 220 Map<String, List<String>> typesChildren, Set<String> done, SchemaManager schemaManager) { 221 if (done.contains(name)) { 222 return; 223 } 224 done.add(name); 225 DocumentType dt = schemaManager.getDocumentType(name); 226 String parentTypeId = NuxeoTypeHelper.getParentTypeId(dt); 227 if (parentTypeId != null) { 228 TypeDefinitionContainer parentType = typeManager.getTypeById(parentTypeId); 229 if (parentType == null) { 230 // if parent was ignored, reparent under cmis:document 231 parentTypeId = BaseTypeId.CMIS_DOCUMENT.value(); 232 } else { 233 if (parentType.getTypeDefinition().getBaseTypeId() != BaseTypeId.CMIS_FOLDER && dt.isFolder()) { 234 // reparent Folderish but child of Document under 235 // cmis:folder 236 parentTypeId = BaseTypeId.CMIS_FOLDER.value(); 237 } 238 } 239 typeManager.addTypeDefinition(NuxeoTypeHelper.constructDocumentType(dt, parentTypeId, cmisVersion)); 240 } 241 // recurse in children 242 List<String> children = typesChildren.get(name); 243 if (children == null) { 244 return; 245 } 246 for (String sub : children) { 247 addTypesRecursively(typeManager, sub, typesChildren, done, schemaManager); 248 } 249 } 250 251 protected void addSecondaryTypes(TypeManagerImpl typeManager, SchemaManager schemaManager) { 252 for (CompositeType type : schemaManager.getFacets()) { 253 typeManager.addTypeDefinition(NuxeoTypeHelper.constructSecondaryType(type, cmisVersion), false); 254 } 255 } 256 257 public String getRootFolderId() { 258 return rootFolderId; 259 } 260 261 public RepositoryInfo getRepositoryInfo(String latestChangeLogToken, CallContext callContext) { 262 cmisVersion = callContext.getCmisVersion(); 263 264 RepositoryInfoImpl repositoryInfo = new RepositoryInfoImpl(); 265 repositoryInfo.setId(repositoryId); 266 repositoryInfo.setName("Nuxeo Repository " + repositoryId); 267 repositoryInfo.setDescription("Nuxeo Repository " + repositoryId); 268 repositoryInfo.setCmisVersionSupported(cmisVersion.value()); 269 repositoryInfo.setPrincipalAnonymous("Guest"); // TODO 270 repositoryInfo.setPrincipalAnyone(SecurityConstants.EVERYONE); 271 repositoryInfo.setThinClientUri(getBaseURL(callContext)); 272 repositoryInfo.setChangesIncomplete(Boolean.FALSE); 273 repositoryInfo.setChangesOnType(Arrays.asList(BaseTypeId.CMIS_DOCUMENT, BaseTypeId.CMIS_FOLDER)); 274 repositoryInfo.setLatestChangeLogToken(latestChangeLogToken); 275 repositoryInfo.setVendorName("Nuxeo"); 276 repositoryInfo.setProductName("Nuxeo OpenCMIS Connector"); 277 String version = Framework.getProperty(Environment.DISTRIBUTION_VERSION, "5.5 dev"); 278 repositoryInfo.setProductVersion(version); 279 repositoryInfo.setRootFolder(rootFolderId); 280 repositoryInfo.setExtensionFeature(Collections.<ExtensionFeature> emptyList()); 281 282 // capabilities 283 284 RepositoryCapabilitiesImpl caps = new RepositoryCapabilitiesImpl(); 285 caps.setAllVersionsSearchable(Boolean.TRUE); 286 caps.setCapabilityAcl(CapabilityAcl.MANAGE); 287 caps.setCapabilityChanges(CapabilityChanges.OBJECTIDSONLY); 288 caps.setCapabilityContentStreamUpdates(CapabilityContentStreamUpdates.PWCONLY); 289 caps.setCapabilityJoin(supportsJoins ? CapabilityJoin.INNERANDOUTER : CapabilityJoin.NONE); 290 caps.setCapabilityQuery(CapabilityQuery.BOTHCOMBINED); 291 caps.setCapabilityRendition(CapabilityRenditions.READ); 292 caps.setIsPwcSearchable(Boolean.TRUE); 293 caps.setIsPwcUpdatable(Boolean.TRUE); 294 caps.setSupportsGetDescendants(Boolean.TRUE); 295 caps.setSupportsGetFolderTree(Boolean.TRUE); 296 caps.setSupportsMultifiling(Boolean.FALSE); 297 caps.setSupportsUnfiling(Boolean.FALSE); 298 caps.setSupportsVersionSpecificFiling(Boolean.FALSE); 299 caps.setNewTypeSettableAttributes(new NewTypeSettableAttributesImpl()); 300 caps.setCreatablePropertyTypes(new CreatablePropertyTypesImpl()); 301 repositoryInfo.setCapabilities(caps); 302 303 // ACL capabilities 304 305 AclCapabilitiesDataImpl aclCaps = new AclCapabilitiesDataImpl(); 306 aclCaps.setAclPropagation(AclPropagation.PROPAGATE); 307 aclCaps.setSupportedPermissions(SupportedPermissions.REPOSITORY); 308 309 List<PermissionDefinition> permDefs = new ArrayList<>(); 310 addPermissionDefinitions(permDefs); 311 aclCaps.setPermissionDefinitionData(permDefs); 312 313 Map<String, PermissionMapping> permMap = new HashMap<>(); 314 addPermissionMapping(permMap, CAN_GET_DESCENDENTS_FOLDER, READ); 315 addPermissionMapping(permMap, CAN_GET_CHILDREN_FOLDER, READ); 316 addPermissionMapping(permMap, CAN_GET_PARENTS_FOLDER, READ); 317 addPermissionMapping(permMap, CAN_GET_FOLDER_PARENT_OBJECT, READ); 318 addPermissionMapping(permMap, CAN_CREATE_DOCUMENT_FOLDER, WRITE); 319 addPermissionMapping(permMap, CAN_CREATE_FOLDER_FOLDER, WRITE); 320 // no CAN_CREATE_POLICY_FOLDER due to spec bug 321 addPermissionMapping(permMap, CAN_CREATE_RELATIONSHIP_SOURCE, READ); 322 addPermissionMapping(permMap, CAN_CREATE_RELATIONSHIP_TARGET, READ); 323 addPermissionMapping(permMap, CAN_GET_PROPERTIES_OBJECT, READ); 324 addPermissionMapping(permMap, CAN_VIEW_CONTENT_OBJECT, READ); 325 addPermissionMapping(permMap, CAN_UPDATE_PROPERTIES_OBJECT, WRITE); 326 addPermissionMapping(permMap, CAN_MOVE_OBJECT, WRITE); 327 addPermissionMapping(permMap, CAN_MOVE_TARGET, WRITE); 328 addPermissionMapping(permMap, CAN_MOVE_SOURCE, WRITE); 329 addPermissionMapping(permMap, CAN_DELETE_OBJECT, WRITE); 330 addPermissionMapping(permMap, CAN_DELETE_TREE_FOLDER, WRITE); 331 addPermissionMapping(permMap, CAN_SET_CONTENT_DOCUMENT, WRITE); 332 addPermissionMapping(permMap, CAN_DELETE_CONTENT_DOCUMENT, WRITE); 333 addPermissionMapping(permMap, CAN_ADD_TO_FOLDER_OBJECT, WRITE); 334 addPermissionMapping(permMap, CAN_ADD_TO_FOLDER_FOLDER, WRITE); 335 addPermissionMapping(permMap, CAN_REMOVE_FROM_FOLDER_OBJECT, WRITE); 336 addPermissionMapping(permMap, CAN_REMOVE_FROM_FOLDER_FOLDER, WRITE); 337 addPermissionMapping(permMap, CAN_CHECKOUT_DOCUMENT, WRITE); 338 addPermissionMapping(permMap, CAN_CANCEL_CHECKOUT_DOCUMENT, WRITE); 339 addPermissionMapping(permMap, CAN_CHECKIN_DOCUMENT, WRITE); 340 addPermissionMapping(permMap, CAN_GET_ALL_VERSIONS_VERSION_SERIES, READ); 341 addPermissionMapping(permMap, CAN_GET_OBJECT_RELATIONSHIPS_OBJECT, READ); 342 addPermissionMapping(permMap, CAN_ADD_POLICY_OBJECT, WRITE); 343 addPermissionMapping(permMap, CAN_ADD_POLICY_POLICY, WRITE); 344 addPermissionMapping(permMap, CAN_REMOVE_POLICY_OBJECT, WRITE); 345 addPermissionMapping(permMap, CAN_REMOVE_POLICY_POLICY, WRITE); 346 addPermissionMapping(permMap, CAN_GET_APPLIED_POLICIES_OBJECT, READ); 347 addPermissionMapping(permMap, CAN_GET_ACL_OBJECT, READ); 348 addPermissionMapping(permMap, CAN_APPLY_ACL_OBJECT, ALL); 349 aclCaps.setPermissionMappingData(permMap); 350 351 repositoryInfo.setAclCapabilities(aclCaps); 352 353 return repositoryInfo; 354 } 355 356 @SuppressWarnings("unchecked") 357 protected static void addPermissionDefinitions(List<PermissionDefinition> permDefs) { 358 addPermissionDefinition(permDefs, READ, "Read"); // = Nuxeo Read 359 addPermissionDefinition(permDefs, WRITE, "Write"); // = Nuxeo ReadWrite 360 addPermissionDefinition(permDefs, ALL, "All"); // = Nuxeo Everything 361 addPermissionDefinition(permDefs, NUXEO_READ_REMOVE, "Remove"); 362 363 Set<String> done = new HashSet<>(); 364 done.add(SecurityConstants.READ); 365 done.add(SecurityConstants.READ_WRITE); 366 done.add(SecurityConstants.EVERYTHING); 367 done.add(NUXEO_READ_REMOVE); 368 369 /* 370 * Add Nuxeo-specific permissions registered through the permissionsVisibility extension point. 371 */ 372 373 DefaultPermissionProvider permissionProvider = (DefaultPermissionProvider) Framework.getService(PermissionProvider.class); 374 permissionProvider.getUserVisiblePermissionDescriptors(); // init var 375 Map<String, PermissionVisibilityDescriptor> map; 376 try { 377 Field f; 378 f = DefaultPermissionProvider.class.getDeclaredField("mergedPermissionsVisibility"); 379 f.setAccessible(true); 380 map = (Map<String, PermissionVisibilityDescriptor>) f.get(permissionProvider); 381 } catch (NoSuchFieldException | SecurityException | IllegalAccessException e) { 382 throw new RuntimeException(e); 383 } 384 // iterate for all types regisited, not just the default "" 385 for (Entry<String, PermissionVisibilityDescriptor> en : map.entrySet()) { 386 for (String permission : en.getValue().getSortedItems()) { 387 if (!done.add(permission)) { 388 continue; 389 } 390 addPermissionDefinition(permDefs, permission, permission); 391 } 392 } 393 } 394 395 protected static void addPermissionDefinition(List<PermissionDefinition> permDefs, String permission, 396 String description) { 397 PermissionDefinitionDataImpl pd = new PermissionDefinitionDataImpl(); 398 pd.setId(permission); 399 pd.setDescription(description); 400 permDefs.add(pd); 401 } 402 403 protected static void addPermissionMapping(Map<String, PermissionMapping> permMap, String key, String permission) { 404 PermissionMappingDataImpl pm = new PermissionMappingDataImpl(); 405 pm.setKey(key); 406 pm.setPermissions(Collections.singletonList(permission)); 407 permMap.put(key, pm); 408 } 409 410 // Structures are not copied when returned 411 public TypeDefinition getTypeDefinition(String typeId) { 412 TypeDefinitionContainer typec = getTypeManager().getTypeById(typeId); 413 return typec == null ? null : typec.getTypeDefinition(); 414 } 415 416 public boolean hasType(String typeId) { 417 return getTypeManager().hasType(typeId); 418 } 419 420 // Structures are not copied when returned 421 public TypeDefinitionList getTypeChildren(String typeId, Boolean includePropertyDefinitions, BigInteger maxItems, 422 BigInteger skipCount) { 423 return getTypeManager().getTypeChildren(typeId, includePropertyDefinitions, maxItems, skipCount); 424 } 425 426 public List<TypeDefinitionContainer> getTypeDescendants(String typeId, int depth, Boolean includePropertyDefinitions) { 427 return getTypeManager().getTypeDescendants(typeId, depth, includePropertyDefinitions); 428 } 429 430 /** Returns the server base URL (including context). */ 431 private static String getBaseURL(CallContext callContext) { 432 HttpServletRequest request = (HttpServletRequest) callContext.get(CallContext.HTTP_SERVLET_REQUEST); 433 if (request != null) { 434 String baseURL = getServerURL(request); 435 String contextPath = request.getContextPath(); 436 if (contextPath == null) { 437 contextPath = Framework.getProperty(NUXEO_CONTEXT_PATH_PROP, NUXEO_CONTEXT_PATH_DEFAULT); 438 } 439 // add context path 440 return baseURL + contextPath + '/'; 441 } else { 442 return Framework.getProperty(NUXEO_URL_PROP); 443 } 444 } 445 446 /** 447 * Returns the server URL according to virtual hosting headers (without trailing slash). 448 */ 449 private static String getServerURL(HttpServletRequest request) { 450 String url = null; 451 // Detect Nuxeo specific header for VH 452 String nuxeoVH = request.getHeader(NUXEO_VH_HEADER); 453 if (nuxeoVH == null) { 454 nuxeoVH = Framework.getProperty(VH_PARAM); 455 } 456 if (nuxeoVH != null && nuxeoVH.startsWith("http")) { 457 url = nuxeoVH; 458 } else { 459 // default values 460 String scheme = request.getScheme(); 461 String serverName = request.getServerName(); 462 int serverPort = request.getServerPort(); 463 // Detect virtual hosting based in standard header 464 String forwardedHost = request.getHeader(X_FORWARDED_HOST); 465 if (forwardedHost != null) { 466 if (forwardedHost.contains(":")) { 467 String[] split = forwardedHost.split(":"); 468 serverName = split[0]; 469 serverPort = Integer.parseInt(split[1]); 470 } else { 471 serverName = forwardedHost; 472 serverPort = 80; // fallback 473 } 474 } 475 url = buildURL(scheme, serverName, serverPort); 476 } 477 // strip trailing slash 478 if (url.endsWith("/")) { 479 url = url.substring(0, url.length() - 1); 480 } 481 return url; 482 } 483 484 /** Builds an URL (without trailing slash). */ 485 private static String buildURL(String scheme, String serverName, int serverPort) { 486 StringBuilder sb = new StringBuilder(); 487 sb.append(scheme); 488 sb.append("://"); 489 sb.append(serverName); 490 if (serverPort != 0) { 491 if ("http".equals(scheme) && serverPort != 80 || "https".equals(scheme) && serverPort != 443) { 492 sb.append(':'); 493 sb.append(serverPort); 494 } 495 } 496 return sb.toString(); 497 } 498 499}