001/* 002 * Copyright 2011-2013 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 boolean authenticate(final String userID, final String password) { 056 return false; 057 } 058 059 /** 060 * {@inheritDoc} 061 */ 062 @Override 063 public void finalizeBackend() { 064 // Nothing to do. 065 } 066 067 /** 068 * {@inheritDoc} 069 */ 070 @Override 071 public ResourceDescriptor getResource(final GetResourceRequest request) 072 throws SCIMException { 073 ResourceDescriptor resourceDescriptor = null; 074 for(ResourceDescriptor rd : 075 application.getBackend().getResourceDescriptors()) 076 { 077 String id = rd.getSchema() + 078 SCIMConstants.SEPARATOR_CHAR_QUALIFIED_ATTRIBUTE + rd.getName(); 079 if(id.equalsIgnoreCase(request.getResourceID())) 080 { 081 resourceDescriptor = rd; 082 break; 083 } 084 } 085 086 // Try to find a match in case the schema name was not provided. 087 if (resourceDescriptor == null) 088 { 089 for(ResourceDescriptor rd : 090 application.getBackend().getResourceDescriptors()) 091 { 092 if(rd.getName().equalsIgnoreCase(request.getResourceID())) 093 { 094 resourceDescriptor = rd; 095 break; 096 } 097 } 098 } 099 100 if(resourceDescriptor == null) 101 { 102 throw new ResourceNotFoundException("No Resource Schema with ID " + 103 request.getResourceID() + " exists"); 104 } 105 106 return copyAndSetIdAndMetaAttributes(resourceDescriptor, request); 107 } 108 109 /** 110 * {@inheritDoc} 111 */ 112 @Override 113 public Resources getResources(final GetResourcesRequest request) 114 throws SCIMException { 115 List<BaseResource> rds = 116 new ArrayList<BaseResource>( 117 application.getBackend().getResourceDescriptors().size()); 118 119 for(ResourceDescriptor resourceDescriptor : 120 application.getBackend().getResourceDescriptors()) 121 { 122 ResourceDescriptor copy = 123 copyAndSetIdAndMetaAttributes(resourceDescriptor, request); 124 if(request.getFilter() == null || 125 copy.getScimObject().matchesFilter(request.getFilter())) 126 { 127 rds.add(copy); 128 } 129 } 130 131 int fromIndex = 0; 132 int total = rds.size(); 133 if(request.getPageParameters() != null) 134 { 135 fromIndex = request.getPageParameters().getStartIndex() - 1; 136 int endIndex = 137 Math.min(request.getPageParameters().getCount() + fromIndex, 138 rds.size()); 139 rds = rds.subList(fromIndex, endIndex); 140 } 141 142 return new Resources<BaseResource>(rds, total, fromIndex + 1); 143 } 144 145 /** 146 * {@inheritDoc} 147 */ 148 @Override 149 public BaseResource postResource(final PostResourceRequest request) 150 throws SCIMException { 151 throw new UnsupportedOperationException("POST operations are not allowed " + 152 "on the Resource Schema"); 153 } 154 155 /** 156 * {@inheritDoc} 157 */ 158 @Override 159 public void deleteResource(final DeleteResourceRequest request) 160 throws SCIMException { 161 throw new UnsupportedOperationException("DELETE operations are not " + 162 "allowed on the Resource Schema"); 163 } 164 165 /** 166 * {@inheritDoc} 167 */ 168 @Override 169 public BaseResource putResource(final PutResourceRequest request) 170 throws SCIMException { 171 throw new UnsupportedOperationException("PUT operations are not allowed " + 172 "on the Resource Schema"); 173 } 174 175 /** 176 * {@inheritDoc} 177 */ 178 @Override 179 public BaseResource patchResource(final PatchResourceRequest request) 180 throws SCIMException { 181 throw new UnsupportedOperationException("PATCH operations are not " + 182 "allowed on the Resource Schema"); 183 } 184 185 @Override 186 public Collection<ResourceDescriptor> getResourceDescriptors() 187 { 188 return Collections.singleton(CoreSchema.RESOURCE_SCHEMA_DESCRIPTOR); 189 } 190 191 /** 192 * Make a copy of the ResourceDescriptor and set the id and meta attributes 193 * from the provided information. 194 * 195 * @param resource The SCIM object whose id and meta attributes are to be 196 * set. 197 * @param request The SCIM request. 198 * @return The copy of the ResourceDescriptor. 199 */ 200 public static ResourceDescriptor copyAndSetIdAndMetaAttributes( 201 final ResourceDescriptor resource, 202 final ResourceReturningRequest request) 203 { 204 ResourceDescriptor copy = 205 ResourceDescriptor.RESOURCE_DESCRIPTOR_FACTORY.createResource( 206 resource.getResourceDescriptor(), 207 new SCIMObject(resource.getScimObject())); 208 209 String id = resource.getSchema() + 210 SCIMConstants.SEPARATOR_CHAR_QUALIFIED_ATTRIBUTE + resource.getName(); 211 copy.setId(id); 212 213 final UriBuilder uriBuilder = UriBuilder.fromUri(request.getBaseURL()); 214 if (!request.getBaseURL().getPath().endsWith("v1/")) 215 { 216 uriBuilder.path("v1"); 217 } 218 uriBuilder.path(resource.getResourceDescriptor().getEndpoint()); 219 uriBuilder.path(id); 220 221 copy.setMeta(new Meta(null, null, uriBuilder.build(), null)); 222 223 // Pare down the attributes to those requested. 224 return ResourceDescriptor.RESOURCE_DESCRIPTOR_FACTORY.createResource( 225 resource.getResourceDescriptor(), 226 request.getAttributes().pareObject(copy.getScimObject())); 227 } 228}