001/* 002 * Copyright 2011-2015 UnboundID Corp. 003 * 004 * This program is free software; you can redistribute it and/or modify 005 * it under the terms of the GNU General Public License (GPLv2 only) 006 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 007 * as published by the Free Software Foundation. 008 * 009 * This program 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 012 * GNU General Public License for more details. 013 * 014 * You should have received a copy of the GNU General Public License 015 * along with this program; if not, see <http://www.gnu.org/licenses>. 016 */ 017 018package com.unboundid.scim.sdk; 019 020import com.unboundid.scim.data.BaseResource; 021import com.unboundid.scim.data.Meta; 022import com.unboundid.scim.schema.CoreSchema; 023import com.unboundid.scim.schema.ResourceDescriptor; 024import com.unboundid.scim.wink.SCIMApplication; 025 026import javax.ws.rs.core.UriBuilder; 027import java.util.ArrayList; 028import java.util.Collection; 029import java.util.Collections; 030import java.util.List; 031 032/** 033 * This class provides an implementation of the SCIM server backend API that 034 * serves up the resource schema from a collection of ResourceDescriptors. 035 */ 036public class ResourceSchemaBackend extends SCIMBackend 037{ 038 private final SCIMApplication application; 039 040 /** 041 * Create a new ResourceSchemaBackend that serves up the schema provided 042 * from the ResourceDescriptors. 043 * 044 * @param application The SCIM JAX-RS application associated with this 045 * backend. 046 */ 047 public ResourceSchemaBackend(final SCIMApplication application) { 048 this.application = application; 049 } 050 051 /** 052 * {@inheritDoc} 053 */ 054 @Override 055 public void finalizeBackend() { 056 // Nothing to do. 057 } 058 059 /** 060 * {@inheritDoc} 061 */ 062 @Override 063 public ResourceDescriptor getResource(final GetResourceRequest request) 064 throws SCIMException { 065 ResourceDescriptor resourceDescriptor = null; 066 for(ResourceDescriptor rd : 067 application.getBackend().getResourceDescriptors()) 068 { 069 String id = rd.getSchema() + 070 SCIMConstants.SEPARATOR_CHAR_QUALIFIED_ATTRIBUTE + rd.getName(); 071 if(id.equalsIgnoreCase(request.getResourceID())) 072 { 073 resourceDescriptor = rd; 074 break; 075 } 076 } 077 078 // Try to find a match in case the schema name was not provided. 079 if (resourceDescriptor == null) 080 { 081 for(ResourceDescriptor rd : 082 application.getBackend().getResourceDescriptors()) 083 { 084 if(rd.getName().equalsIgnoreCase(request.getResourceID())) 085 { 086 resourceDescriptor = rd; 087 break; 088 } 089 } 090 } 091 092 if(resourceDescriptor == null) 093 { 094 throw new ResourceNotFoundException("No Resource Schema with ID " + 095 request.getResourceID() + " exists"); 096 } 097 098 return copyAndSetIdAndMetaAttributes(resourceDescriptor, request); 099 } 100 101 /** 102 * {@inheritDoc} 103 */ 104 @Override 105 public Resources getResources(final GetResourcesRequest request) 106 throws SCIMException { 107 List<BaseResource> rds = 108 new ArrayList<BaseResource>( 109 application.getBackend().getResourceDescriptors().size()); 110 111 for(ResourceDescriptor resourceDescriptor : 112 application.getBackend().getResourceDescriptors()) 113 { 114 ResourceDescriptor copy = 115 copyAndSetIdAndMetaAttributes(resourceDescriptor, request); 116 if(request.getFilter() == null || 117 copy.getScimObject().matchesFilter(request.getFilter())) 118 { 119 rds.add(copy); 120 } 121 } 122 123 int fromIndex = 0; 124 int total = rds.size(); 125 if(request.getPageParameters() != null) 126 { 127 fromIndex = request.getPageParameters().getStartIndex() - 1; 128 int endIndex = 129 Math.min(request.getPageParameters().getCount() + fromIndex, 130 rds.size()); 131 rds = rds.subList(fromIndex, endIndex); 132 } 133 134 return new Resources<BaseResource>(rds, total, fromIndex + 1); 135 } 136 137 /** 138 * {@inheritDoc} 139 */ 140 @Override 141 public BaseResource postResource(final PostResourceRequest request) 142 throws SCIMException { 143 throw new UnsupportedOperationException("POST operations are not allowed " + 144 "on the Resource Schema"); 145 } 146 147 /** 148 * {@inheritDoc} 149 */ 150 @Override 151 public void deleteResource(final DeleteResourceRequest request) 152 throws SCIMException { 153 throw new UnsupportedOperationException("DELETE operations are not " + 154 "allowed on the Resource Schema"); 155 } 156 157 /** 158 * {@inheritDoc} 159 */ 160 @Override 161 public BaseResource putResource(final PutResourceRequest request) 162 throws SCIMException { 163 throw new UnsupportedOperationException("PUT operations are not allowed " + 164 "on the Resource Schema"); 165 } 166 167 /** 168 * {@inheritDoc} 169 */ 170 @Override 171 public BaseResource patchResource(final PatchResourceRequest request) 172 throws SCIMException { 173 throw new UnsupportedOperationException("PATCH operations are not " + 174 "allowed on the Resource Schema"); 175 } 176 177 /** 178 * {@inheritDoc} 179 */ 180 @Override 181 public Collection<ResourceDescriptor> getResourceDescriptors() 182 { 183 return Collections.singleton(CoreSchema.RESOURCE_SCHEMA_DESCRIPTOR); 184 } 185 186 /** 187 * {@inheritDoc} 188 */ 189 @Override 190 public void getStreamedResources( 191 final GetStreamedResourcesRequest request, 192 final StreamedResultListener listener) throws SCIMException 193 { 194 throw new UnsupportedOperationException( 195 "Streamed Query not supported on Schema endpoint"); 196 } 197 198 /** 199 * Make a copy of the ResourceDescriptor and set the id and meta attributes 200 * from the provided information. 201 * 202 * @param resource The SCIM object whose id and meta attributes are to be 203 * set. 204 * @param request The SCIM request. 205 * @return The copy of the ResourceDescriptor. 206 */ 207 public static ResourceDescriptor copyAndSetIdAndMetaAttributes( 208 final ResourceDescriptor resource, 209 final ResourceReturningRequest request) 210 { 211 ResourceDescriptor copy = 212 ResourceDescriptor.RESOURCE_DESCRIPTOR_FACTORY.createResource( 213 resource.getResourceDescriptor(), 214 new SCIMObject(resource.getScimObject())); 215 216 String id = resource.getSchema() + 217 SCIMConstants.SEPARATOR_CHAR_QUALIFIED_ATTRIBUTE + resource.getName(); 218 copy.setId(id); 219 220 final UriBuilder uriBuilder = UriBuilder.fromUri(request.getBaseURL()); 221 if (!request.getBaseURL().getPath().endsWith("v1/")) 222 { 223 uriBuilder.path("v1"); 224 } 225 uriBuilder.path(resource.getResourceDescriptor().getEndpoint()); 226 uriBuilder.path(id); 227 228 copy.setMeta(new Meta(null, null, uriBuilder.build(), null)); 229 230 // Pare down the attributes to those requested. 231 return ResourceDescriptor.RESOURCE_DESCRIPTOR_FACTORY.createResource( 232 resource.getResourceDescriptor(), 233 request.getAttributes().pareObject(copy.getScimObject())); 234 } 235}